19 Commits

Author SHA1 Message Date
Avi Deitcher
860163a9c7 Merge pull request #3863 from deitch/rationalize-build-pull
Rationalize build pull
2022-11-07 09:54:48 +02:00
Avi Deitcher
bfa4a33b0d Merge pull request #3865 from deitch/bump-vz
bump virtualization-framework library to v3.0.0
2022-11-07 09:54:08 +02:00
Avi Deitcher
121002bae4 Merge pull request #3862 from deitch/canonical-tag
option to show canonical tag
2022-11-07 09:53:50 +02:00
Avi Deitcher
11fe19138d bump virtualization-framework library to v3.0.0
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2022-11-02 20:20:59 +02:00
Avi Deitcher
a3995bb724 build should check and only pull if requested
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2022-11-01 22:00:50 +02:00
Avi Deitcher
f870c16ea6 option to show canonical tag
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2022-11-01 15:15:09 +02:00
Avi Deitcher
9ea2d6dcd9 rationalize pull build
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2022-11-01 12:51:44 +02:00
Avi Deitcher
b17c93a635 Merge pull request #3860 from deitch/shard-packages-tests
add sharding option
2022-11-01 12:50:48 +02:00
Avi Deitcher
cf7d83bb13 add sharding option
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2022-10-30 11:16:42 +02:00
Avi Deitcher
f8947c6ae6 Merge pull request #3859 from deitch/safety-check-platforms
catch error with descriptor missing platform
2022-10-30 11:15:58 +02:00
Avi Deitcher
302c0051ec Merge pull request #3857 from deitch/fix-network-control
fix network build modes
2022-10-30 11:15:42 +02:00
Rolf Neugebauer
5200e52816 Merge pull request #3858 from deitch/makefile-rtf-tests
move rtf commands from GHA into make test; remove unused artifacts
2022-10-25 00:10:37 +01:00
Avi Deitcher
33180047f5 catch error with descriptor missing platform
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2022-10-24 21:44:50 +03:00
Avi Deitcher
7c2b9b3b3a move rtf commands from GHA into make test; remove unused artifacts
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2022-10-24 12:50:28 +03:00
Avi Deitcher
2dfc1dcf3e fix network build modes
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2022-10-24 11:45:45 +03:00
Rolf Neugebauer
25c8e68f98 Merge pull request #3855 from dgageot/retore-pad4
Fix initrd image padding
2022-10-22 11:40:25 +01:00
Rolf Neugebauer
7ff1e91875 Merge pull request #3856 from deitch/update-buildkit
update latest buildkit library to support advanced dockerfile scanning, other libs, go 1.19
2022-10-22 11:38:04 +01:00
Avi Deitcher
eafdb0db0c update latest buildkit library to support advanced dockerfile scanning. Also go 1.19 and other libs
Signed-off-by: Avi Deitcher <avi@deitcher.net>
2022-10-20 13:47:42 +03:00
David Gageot
c61ddd0482 Remove pad4 writer because it's buggy and doesn't seem required
According to https://docs.kernel.org/driver-api/early-userspace/buffer-format.html

Signed-off-by: David Gageot <david.gageot@docker.com>
2022-10-18 19:03:49 +02:00
773 changed files with 96226 additions and 20087 deletions

View File

@@ -128,6 +128,9 @@ jobs:
name: Packages Tests
needs: [ build_packages, build ]
runs-on: ubuntu-latest
strategy:
matrix:
shard: [1/10,2/10,3/10,4/10,5/10,6/10,7/10,8/10,9/10,10/10]
steps:
- name: Check out code
uses: actions/checkout@v3
@@ -174,9 +177,7 @@ jobs:
${{ runner.os }}-linuxkit-
- name: Run Tests
run: |
cd test
rtf -l build -v run -x linuxkit.packages
run: make test TEST_SUITE=linuxkit.packages TEST_SHARD=${{ matrix.shard }}
test_kernel:
name: Kernel Tests
@@ -220,9 +221,7 @@ jobs:
/usr/local/bin/linuxkit version
- name: Run Tests
run: |
cd test
rtf -l build -v run -x linuxkit.kernel
run: make test TEST_SUITE=linuxkit.kernel
test_linuxkit:
name: LinuxKit Build Tests
@@ -266,9 +265,7 @@ jobs:
/usr/local/bin/linuxkit version
- name: Run Tests
run: |
cd test
rtf -l build -v run -x linuxkit.build
run: make test TEST_SUITE=linuxkit.build
test_platforms:
name: Platform Tests
@@ -312,9 +309,7 @@ jobs:
/usr/local/bin/linuxkit version
- name: Run Tests
run: |
cd test
rtf -l build -v run -x linuxkit.platforms
run: make test TEST_SUITE=linuxkit.platforms
test_security:
name: Security Tests
@@ -358,6 +353,4 @@ jobs:
/usr/local/bin/linuxkit version
- name: Run Tests
run: |
cd test
rtf -l build -v run -x linuxkit.security
run: make test TEST_SUITE=linuxkit.security

View File

@@ -1,5 +1,9 @@
VERSION="v0.8+"
# test suite to run, blank for all
TEST_SUITE ?=
TEST_SHARD ?=
GO_COMPILE=linuxkit/go-compile:7b1f5a37d2a93cd4a9aa2a87db264d8145944006
ifeq ($(OS),Windows_NT)
@@ -30,7 +34,7 @@ export VERSION GO_COMPILE GOOS GOARCH LOCAL_TARGET LINUXKIT
default: linuxkit $(RTF)
all: default
RTF_COMMIT=2351267f358ce6621c0c0d9a069f361268dba5fc
RTF_COMMIT=1b6277593346dea7e6039d528c4e8321a4bd9eaf
RTF_CMD=github.com/linuxkit/rtf/cmd
RTF_VERSION=0.0
$(RTF): tmp_rtf_bin.tar | bin
@@ -78,10 +82,7 @@ sign:
.PHONY: test
test:
$(MAKE) -C test
.PHONY: collect-artifacts
collect-artifacts: artifacts/test.img.tar.gz artifacts/test-ltp.img.tar.gz
$(MAKE) -C test TEST_SUITE=$(TEST_SUITE) TEST_SHARD=$(TEST_SHARD)
.PHONY: ci ci-tag ci-pr
ci: test-cross

View File

@@ -353,3 +353,60 @@ func (p *Provider) DescriptorWrite(ref *reference.Spec, desc v1.Descriptor) (lkt
&desc,
), nil
}
func (p *Provider) ImageInCache(ref *reference.Spec, trustedRef, architecture string) (bool, error) {
if _, err := p.findImage(ref.String(), architecture); err != nil {
return false, err
}
return true, nil
}
// ImageInRegistry takes an image name and checks that the image manifest or index to which it refers
// exists in the registry.
func (p *Provider) ImageInRegistry(ref *reference.Spec, trustedRef, architecture string) (bool, error) {
image := ref.String()
remoteOptions := []remote.Option{remote.WithAuthFromKeychain(authn.DefaultKeychain)}
log.Debugf("Checking image %s in registry", image)
remoteRef, err := name.ParseReference(image)
if err != nil {
return false, fmt.Errorf("invalid image name %s: %v", image, err)
}
desc, err := remote.Get(remoteRef, remoteOptions...)
if err != nil {
return false, fmt.Errorf("error getting manifest for image %s: %v", image, err)
}
// first attempt as an index
ii, err := desc.ImageIndex()
if err == nil {
log.Debugf("ImageExists retrieved %s as index", remoteRef)
im, err := ii.IndexManifest()
if err != nil {
return false, fmt.Errorf("unable to get IndexManifest: %v", err)
}
for _, m := range im.Manifests {
if m.MediaType.IsImage() && (m.Platform == nil || m.Platform.Architecture == architecture) {
return true, nil
}
}
// we went through all of the manifests and did not find one that matches the target architecture
} else {
var im v1.Image
// try an image
im, err = desc.Image()
if err != nil {
return false, fmt.Errorf("provided image is neither an image nor an index: %s", image)
}
log.Debugf("ImageExists retrieved %s as image", remoteRef)
conf, err := im.ConfigFile()
if err != nil {
return false, fmt.Errorf("unable to get ConfigFile: %v", err)
}
if conf.Architecture == architecture {
return true, nil
}
// the image had the wrong architecture
}
return false, nil
}

View File

@@ -1,26 +1,21 @@
module github.com/linuxkit/linuxkit/src/cmd/linuxkit
go 1.16
go 1.19
require (
github.com/Azure/azure-sdk-for-go v56.3.0+incompatible
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1
github.com/Azure/go-autorest v14.2.1-0.20210115164004-c0fe8b0fea3d+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.24
github.com/Azure/go-autorest/autorest/adal v0.9.18
github.com/Azure/go-autorest/autorest/to v0.4.0
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Code-Hex/vz v0.0.4
github.com/Microsoft/go-winio v0.5.2
github.com/ScaleFT/sshkeys v0.0.0-20181112160850-82451a803681
github.com/aws/aws-sdk-go v1.44.82
github.com/containerd/containerd v1.6.6
github.com/creack/goselect v0.0.0-20180501195510-58854f77ee8d // indirect
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
github.com/containerd/containerd v1.6.8
github.com/docker/buildx v0.8.2
github.com/docker/cli v20.10.17+incompatible
github.com/docker/docker v20.10.17+incompatible
github.com/docker/go-units v0.4.0
github.com/docker/docker v20.10.18+incompatible
github.com/docker/go-units v0.5.0
github.com/estesp/manifest-tool/v2 v2.0.6-0.20220728154431-89d791ab7966
github.com/google/go-containerregistry v0.6.1-0.20211105150418-5c9c442d5d68
github.com/google/uuid v1.3.0
@@ -28,37 +23,124 @@ require (
github.com/gophercloud/utils v0.0.0-20181029231510-34f5991525d1
github.com/hashicorp/go-version v1.2.0
github.com/klauspost/pgzip v1.2.5
github.com/moby/buildkit v0.10.1-0.20220721175135-c75998aec3d4
github.com/moby/buildkit v0.10.1-0.20221020001917-4410c828d67c
github.com/moby/hyperkit v0.0.0-20180416161519-d65b09c1c28a
//github.com/moby/moby v20.10.3-0.20220728162118-71cb54cec41e+incompatible // indirect
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
github.com/moby/vpnkit v0.4.1-0.20200311130018-2ffc1dd8a84e
github.com/moul/gotty-client v1.7.1-0.20180526075433-e5589f6df359
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
github.com/opencontainers/image-spec v1.0.3-0.20220303224323-02efb9a75ee1
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
github.com/packethost/packngo v0.1.1-0.20171201154433-f1be085ecd6f
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/term v1.1.0
github.com/radu-matei/azure-sdk-for-go v5.0.0-beta.0.20161118192335-3b1282355199+incompatible
github.com/radu-matei/azure-vhd-utils v0.0.0-20170531165126-e52754d5569d
github.com/rn/iso9660wrap v0.0.0-20171120145750-baf8d62ad315
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.4.0 // indirect
github.com/stretchr/testify v1.7.2
github.com/surma/gocpio v1.0.2-0.20160926205914-fcb68777e7dc
github.com/vmware/govmomi v0.20.3
github.com/xeipuuv/gojsonschema v1.2.0
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1
golang.org/x/crypto v0.1.0
golang.org/x/net v0.1.0
golang.org/x/oauth2 v0.1.0
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
google.golang.org/api v0.57.0
golang.org/x/sys v0.1.0
golang.org/x/term v0.1.0
google.golang.org/api v0.84.0
gopkg.in/yaml.v2 v2.4.0
)
require (
cloud.google.com/go/compute v1.7.0 // indirect
github.com/Azure/go-autorest v14.2.1-0.20210115164004-c0fe8b0fea3d+incompatible // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/Code-Hex/vz/v3 v3.0.0 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/containerd/continuity v0.3.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.12.0 // indirect
github.com/containerd/ttrpc v1.1.0 // indirect
github.com/containerd/typeurl v1.0.2 // indirect
github.com/creack/goselect v0.0.0-20180501195510-58854f77ee8d // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker-credential-helpers v0.6.4 // indirect
github.com/docker/go-connections v0.4.1-0.20190612165340-fd1b1942c4d5 // indirect
github.com/docker/go-metrics v0.0.1 // indirect
github.com/felixge/httpsnoop v1.0.2 // indirect
github.com/go-logr/logr v1.2.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gofrs/flock v0.7.3 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa // indirect
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/in-toto/in-toto-golang v0.3.3 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/patternmatcher v0.5.0 // indirect
github.com/moby/sys/signal v0.7.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.12.2 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/rs/xid v1.3.0 // indirect
github.com/shibumi/go-pathspec v1.2.0 // indirect
github.com/spf13/cobra v1.4.0 // indirect
github.com/tonistiigi/fsutil v0.0.0-20220930225714-4638ad635be5 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f // indirect
github.com/vbatts/tar-split v0.11.2 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
go.opencensus.io v0.23.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 // indirect
go.opentelemetry.io/otel v1.4.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 // indirect
go.opentelemetry.io/otel/internal/metric v0.27.0 // indirect
go.opentelemetry.io/otel/metric v0.27.0 // indirect
go.opentelemetry.io/otel/sdk v1.4.1 // indirect
go.opentelemetry.io/otel/trace v1.4.1 // indirect
go.opentelemetry.io/proto/otlp v0.12.0 // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90 // indirect
google.golang.org/grpc v1.47.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
oras.land/oras-go v1.2.0 // indirect
)
replace (
// these are for the delicate dance of docker/docker, moby/moby, moby/buildkit, estesp/manifest-tool, oras.land/oras-go, linuxkit/linuxkit
github.com/docker/docker => github.com/moby/moby v20.10.3-0.20220728162118-71cb54cec41e+incompatible

View File

@@ -33,17 +33,27 @@ cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWc
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
cloud.google.com/go/compute v1.7.0 h1:v/k9Eueb8aAJ0vZuxKMrgm6kPhCLZU9HxFU+AFDs9Uk=
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@@ -53,6 +63,7 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
code.gitea.io/sdk/gitea v0.12.0/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0=
@@ -95,7 +106,6 @@ github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdA
github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest v0.11.20/go.mod h1:o3tqFY+QR40VOlk+pV4d77mORO64jOXSgEnPQgLK6JY=
github.com/Azure/go-autorest/autorest v0.11.24 h1:1fIGgHKqVm54KIPT+q8Zmd1QlVsmHqeUGso5qm2BqqE=
github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
@@ -106,7 +116,6 @@ github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMl
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.15/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A=
github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ=
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
@@ -140,6 +149,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Code-Hex/vz v0.0.4 h1:1rM8ijE+znlrOeYIer441cSwpYq2rk57Fd3dRpxUDUA=
github.com/Code-Hex/vz v0.0.4/go.mod h1:UeHKXSv3hP7BzU6IaVE/a7VHSHUHpqbS3oVko4O5UYI=
github.com/Code-Hex/vz/v3 v3.0.0 h1:UuYAZz8NF8n+R4MLfn/lpUlepgzZ8BlhKtioQ+q9LXk=
github.com/Code-Hex/vz/v3 v3.0.0/go.mod h1:+xPQOXVzNaZ4OeIIhlJFumtbFhsvRfqKwX7wuZS4dFA=
github.com/Djarvur/go-err113 v0.0.0-20200410182137-af658d038157/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
github.com/Djarvur/go-err113 v0.1.0/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo=
@@ -172,10 +183,8 @@ github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+V
github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
github.com/Microsoft/hcsshim v0.9.1/go.mod h1:Y/0uV2jUab5kBI7SQgl62at0AVX7uaruzADAVmxm3eM=
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo=
github.com/Microsoft/hcsshim v0.9.3/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim v0.9.4 h1:mnUj0ivWy6UzbB1uLFqKR6F+ZyiDc7j4iGgHTpO+5+I=
github.com/Microsoft/hcsshim/test v0.0.0-20200826032352-301c83a30e7c/go.mod h1:30A5igQ91GEmhYJF8TaRP79pMBOYynRsyOByfVV0dU4=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
@@ -238,24 +247,6 @@ github.com/aws/aws-sdk-go v1.31.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU
github.com/aws/aws-sdk-go v1.34.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.44.82 h1:Miji7nHIMxTWfa831nZf8XAcMWGLaT+PvsS6CdbMG7M=
github.com/aws/aws-sdk-go v1.44.82/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go-v2 v1.16.3/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1/go.mod h1:n8Bs1ElDD2wJ9kCRTczA83gYbBmjSwZp3umc6zF4EeM=
github.com/aws/aws-sdk-go-v2/config v1.15.5/go.mod h1:ZijHHh0xd/A+ZY53az0qzC5tT46kt4JVCePf2NX9Lk4=
github.com/aws/aws-sdk-go-v2/credentials v1.12.0/go.mod h1:9YWk7VW+eyKsoIL6/CljkTrNVWBSK9pkqOPUuijid4A=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.4/go.mod h1:u/s5/Z+ohUQOPXl00m2yJVyioWDECsbpXTQlaqSlufc=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.10/go.mod h1:p+ul5bLZSDRRXCZ/vePvfmZBH9akozXBJA5oMshWa5U=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.10/go.mod h1:F+EZtuIwjlv35kRJPyBGcsA4f7bnSoz15zOQ2lJq1Z4=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.4/go.mod h1:8glyUqVIM4AmeenIsPo0oVh3+NUwnsQml2OFupfQW+0=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.11/go.mod h1:0MR+sS1b/yxsfAPvAESrw8NfwUoxMinDyw6EYR9BS2U=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.1/go.mod h1:l/BbcfqDCT3hePawhy4ZRtewjtdkl6GWtd9/U+1penQ=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1/go.mod h1:GeUru+8VzrTXV/83XyMJ80KpH8xO89VPoUileyNQ+tc=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.5/go.mod h1:S8TVP66AAkMMdYYCNZGvrdEq9YRm+qLXjio4FqRnrEE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.4/go.mod h1:uKkN7qmSIsNJVyMtxNQoCEYMvFEXbOg9fwCJPdfp2u8=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.4/go.mod h1:oudbsSdDtazNj47z1ut1n37re9hDsKpk2ZI3v7KSxq0=
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.9/go.mod h1:iMYipLPXlWpBJ0KFX7QJHZ84rBydHBY8as2aQICTPWk=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.4/go.mod h1:cPDwJwsP4Kff9mldCXAmddjJL6JGQqtA3Mzer2zyr88=
github.com/aws/aws-sdk-go-v2/service/sts v1.16.4/go.mod h1:lfSYenAXtavyX2A1LsViglqlG9eEFYxNryTZS5rn3QE=
github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -282,18 +273,15 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/bshuster-repo/logrus-logstash-hook v1.0.2 h1:JYRWo+QGnQdedgshosug9hxpPYTB9oJ1ZZD3fY31alU=
github.com/bshuster-repo/logrus-logstash-hook v1.0.2/go.mod h1:HgYntJprnHSPaF9VPPPLP1L5S1vMWxRfa1J+vzDrDTw=
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
github.com/bugsnag/bugsnag-go v1.4.1/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
github.com/bugsnag/bugsnag-go v2.1.2+incompatible h1:E7dor84qzwUO8KdCM68CZwq9QOSR7HXlLx3Wj5vui2s=
github.com/bugsnag/bugsnag-go v2.1.2+incompatible/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/bugsnag/panicwrap v1.3.4 h1:A6sXFtDGsgU/4BLf5JT0o5uYg3EeKgGx3Sfs+/uk3pU=
github.com/bugsnag/panicwrap v1.3.4/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw=
github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo=
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A=
@@ -304,7 +292,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
@@ -330,12 +317,14 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/compose-spec/compose-go v1.2.1/go.mod h1:pAy7Mikpeft4pxkFU565/DRHEbDfR84G6AQuiL+Hdg8=
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
@@ -351,7 +340,6 @@ github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4S
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
github.com/containerd/cgroups v1.0.2/go.mod h1:qpbpJ1jmlqsR9f2IyaLPsdkCdnt0rbDVqIDlhuu5tRY=
github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4=
github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
@@ -380,11 +368,9 @@ github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoT
github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ=
github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
github.com/containerd/containerd v1.6.2/go.mod h1:sidY30/InSE1j2vdD1ihtKoJz+lWdaXMdiAeIupaf+s=
github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0=
github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0=
github.com/containerd/containerd v1.6.8 h1:h4dOFDwzHmqFEP754PgfgTeVXFnLiRc6kiqC7tplDJs=
github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
@@ -407,7 +393,6 @@ github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZH
github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk=
github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA=
github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA=
github.com/containerd/go-cni v1.1.6/go.mod h1:BWtoWl5ghVymxu6MBjg79W9NZrCRyHIdUtk4cauMe34=
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g=
@@ -418,19 +403,16 @@ github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6T
github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4=
github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/stargz-snapshotter v0.0.0-20201027054423-3a04e4c2c116/go.mod h1:o59b3PCKVAf9jjiKtCc/9hLAd+5p/rfhBfm6aBcTEr4=
github.com/containerd/stargz-snapshotter v0.11.2/go.mod h1:HfhsbZ98KIoqA2GLmibTpRwMF/lq3utZ0ElV9ARqU7M=
github.com/containerd/stargz-snapshotter v0.11.4 h1:Lvth6E/05juQuWIGGxR5jQnZZkyf0Lq57NrBecVrwZY=
github.com/containerd/stargz-snapshotter v0.11.4/go.mod h1:ojfmncMZd09R7FLo+TGqpwsxZ+X7MkOuqeqgX+KsJWc=
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
github.com/containerd/stargz-snapshotter/estargz v0.9.0/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
github.com/containerd/stargz-snapshotter/estargz v0.11.2/go.mod h1:rjbdAXaytDSIrAy2WAy2kUrJ4ehzDS0eUQLlIb5UCY0=
github.com/containerd/stargz-snapshotter/estargz v0.11.4 h1:LjrYUZpyOhiSaU7hHrdR82/RBoxfGWSaC0VeSSMXqnk=
github.com/containerd/stargz-snapshotter/estargz v0.11.4/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0=
github.com/containerd/stargz-snapshotter/estargz v0.12.0 h1:idtwRTLjk2erqiYhPWy2L844By8NRFYEwYHcXhoIWPM=
github.com/containerd/stargz-snapshotter/estargz v0.12.0/go.mod h1:AIQ59TewBFJ4GOPEQXujcrJ/EKxh5xXZegW1rkR1P/M=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
@@ -452,16 +434,13 @@ github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y=
github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE=
github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8=
github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4=
github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
github.com/containers/ocicrypt v1.1.3/go.mod h1:xpdkbVAuaH3WzbEabUd5yDsl9SwJA5pABH85425Es2g=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@@ -514,7 +493,6 @@ github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQ
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e/go.mod h1:xpWTC2KnJMiDLkoawhsPQcXjvwATEBcbq0xevG2YR9M=
github.com/distribution/distribution/v3 v3.0.0-20211118083504-a29a3c99a684 h1:DBZ2sN7CK6dgvHVpQsQj4sRMCbWTmd17l+5SUCjnQSY=
github.com/distribution/distribution/v3 v3.0.0-20211118083504-a29a3c99a684/go.mod h1:UfCu3YXJJCI+IdnqGgYP82dk2+Joxmv+mUTVBES6wac=
github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/buildx v0.8.2 h1:dsd3F0hhmUydFX/KFrvbK81JvlTA4T3Iy0lwDJt4PsU=
@@ -523,9 +501,7 @@ github.com/docker/cli v0.0.0-20190925022749-754388324470/go.mod h1:JLrzqnKDaYBop
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v20.10.0-beta1.0.20201029214301-1d20b15adc38+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v20.10.9+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v20.10.11+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v20.10.12+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v20.10.14+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M=
github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.4.0/go.mod h1:rgW5KKdNpLMBIuH4WQ/1RNh38nH+/Ay5jgL4P0ZMPpY=
@@ -550,13 +526,13 @@ github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libnetwork v0.8.0-dev.2.0.20200917202933-d0951081b35f/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/libtrust v0.0.0-20150526203908-9cbd2a1374f4/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@@ -578,6 +554,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/estesp/manifest-tool/v2 v2.0.6-0.20220728154431-89d791ab7966 h1:Hlw3XgTSejseEVY+URYLZKmJf2iXDT9IzBa/rvJZ8zc=
github.com/estesp/manifest-tool/v2 v2.0.6-0.20220728154431-89d791ab7966/go.mod h1:xXnTTBEDX1yic5KumuBnxU9+8jdVA4vuJkioPzwredI=
@@ -587,7 +564,6 @@ github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
@@ -677,9 +653,7 @@ github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQq
github.com/gofrs/flock v0.7.3 h1:I0EKY9l8HZCXTMYC4F80vwT6KNypV9uYKP3Alm/hjmQ=
github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
github.com/gogo/googleapis v1.3.2/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
@@ -695,8 +669,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -776,8 +751,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.0.0-20191010200024-a3d713f9b7f8/go.mod h1:KyKXa9ciM8+lgMXwOVsXi7UxGrsf9mM61Mzs+xKUrKE=
github.com/google/go-containerregistry v0.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4=
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
@@ -809,7 +785,6 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
@@ -826,18 +801,24 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s=
github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa h1:7MYGT2XEMam7Mtzv1yDUYXANedWvwk3HKkR3MyGowy8=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=
github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0 h1:6DWmvNpomjL1+3liNSZbVns3zsYzzCjm6pRBO1tLeso=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
github.com/googleapis/gax-go/v2 v2.4.0 h1:dS9eYAjhrE2RjmzYw2XAPvcXfmcQLtFEQWn0CR82awk=
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
github.com/gookit/color v1.2.4/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
@@ -928,6 +909,8 @@ github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/in-toto/in-toto-golang v0.3.3 h1:tkkEBU5i09UEeWKnrp6Rq4fXKAfpVXYMLRO5mDfnb3I=
github.com/in-toto/in-toto-golang v0.3.3/go.mod h1:dbXecHGZSqRubmm5TXtvDSZT5JyaKD7ebVTiC2aMLWY=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ=
@@ -985,8 +968,9 @@ github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A=
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.7/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
@@ -1030,7 +1014,6 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
@@ -1049,13 +1032,13 @@ github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOq
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM=
github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -1076,14 +1059,16 @@ github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ=
github.com/moby/buildkit v0.10.1-0.20220403220257-10e6f94bf90d/go.mod h1:WvwAZv8aRScHkqc/+X46cRC2CKMKpqcaX+pRvUTtPes=
github.com/moby/buildkit v0.10.1-0.20220721175135-c75998aec3d4 h1:+AwP6ma57EBQ5+eOSsg29MAylks33kt2MverACSqJv0=
github.com/moby/buildkit v0.10.1-0.20220721175135-c75998aec3d4/go.mod h1:yle9eiU1fiJ/WhC4VTLOaQ6rxFou1mc4AhwScHwysi0=
github.com/moby/buildkit v0.10.1-0.20221020001917-4410c828d67c h1:3PkKnyxPVTc3yeHL5FkvuxgpC3etKNmJ0joofoGi+6E=
github.com/moby/buildkit v0.10.1-0.20221020001917-4410c828d67c/go.mod h1:puBC74FaCtIyLaIp95LzzLutPkKdDIdT+B8itnVVLBs=
github.com/moby/hyperkit v0.0.0-20180416161519-d65b09c1c28a h1:hExo7kltIidoitYnXsnqfvkJXG3YEMbHuQbf9nOMvow=
github.com/moby/hyperkit v0.0.0-20180416161519-d65b09c1c28a/go.mod h1:zGAVB/FkAf4ozkR8CCuj4LcVuErrNsj9APTDFvhOckw=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/moby v20.10.3-0.20220728162118-71cb54cec41e+incompatible h1:7Hfzx0UTpVuA+EHmZnMkYMqXHcB+emJ7RhAnLC9edxI=
github.com/moby/moby v20.10.3-0.20220728162118-71cb54cec41e+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo=
github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
@@ -1093,10 +1078,11 @@ github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+S
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/mountinfo v0.6.0 h1:gUDhXQx58YNrpHlK4nSL+7y2pxFZkUcXqzFDKWdC0Oo=
github.com/moby/sys/mountinfo v0.6.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/signal v0.6.0 h1:aDpY94H8VlhTGa9sNYUFCFsMZIUh5wm0B6XkIoJj/iY=
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
@@ -1128,7 +1114,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@@ -1147,7 +1132,6 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -1159,7 +1143,6 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -1171,9 +1154,8 @@ github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.2-0.20210730191737-8e42a01fb1b7/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.3-0.20220303224323-02efb9a75ee1 h1:9iFHD5Kt9hkOfeawBNiEeEaV7bmC4/Z5wJp8E9BptMs=
github.com/opencontainers/image-spec v1.0.3-0.20220303224323-02efb9a75ee1/go.mod h1:K/JAU0m27RFhDRX4PcFdIKntROP6y5Ed6O91aZYDQfs=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc10/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
@@ -1183,9 +1165,7 @@ github.com/opencontainers/runc v1.0.0-rc92/go.mod h1:X1zlU4p7wOlX4+WRCz+hvlRv8ph
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -1199,14 +1179,14 @@ github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqi
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/selinux v1.10.1 h1:09LIPVRP3uuZGQvgR+SgMSNBd1Eb3vlRbGqQpoHsF8w=
github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/selinux v1.10.2 h1:NFy2xCsjn7+WspbfZkUd5zyVeisV7VFbPSP96+8/ha4=
github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/package-url/packageurl-go v0.1.0 h1:efWBc98O/dBZRg1pw2xiDzovnlMjCa9NPnfaiBduh8I=
github.com/packethost/packngo v0.1.1-0.20171201154433-f1be085ecd6f h1:eJOXAByy+kpuTpq3wyOWYeoo1anPMDp6TsdzBcncuQ4=
github.com/packethost/packngo v0.1.1-0.20171201154433-f1be085ecd6f/go.mod h1:otzZQXgoO96RTzDB/Hycg0qZcXZsWJGJRSXbmEIJ+4M=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -1218,7 +1198,6 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
@@ -1245,9 +1224,9 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34=
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -1300,11 +1279,11 @@ github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYe
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryancurrah/gomodguard v1.0.4/go.mod h1:9T/Cfuxs5StfsocWr4WzDL36HqnX0fVb9d5fSEaLhoE=
@@ -1321,12 +1300,13 @@ github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83/go.mod h1:vvbZ2Ae7AzSq3/kywjUDxSNq2SJ27RxCz2un0H3ePqE=
github.com/securego/gosec v0.0.0-20200401082031-e946c8c39989/go.mod h1:i9l/TNj+yDFh9SZXUTvspXTjbFXgZGP/UvhU1S65A4A=
github.com/securego/gosec/v2 v2.3.0/go.mod h1:UzeVyUXbxukhLeHKV3VVqo7HdoQR9MrRfFmZYotn8ME=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
github.com/shibumi/go-pathspec v1.2.0 h1:KVKEDHYk7bQolRMs7nfzjT3SBOCgcXFJzccnj9bsGbA=
github.com/shibumi/go-pathspec v1.2.0/go.mod h1:bDxCftD0fST3qXIlHoQ/fChsU4mWMVklXp1yPErQaaY=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
@@ -1424,10 +1404,9 @@ github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dS
github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85/go.mod h1:a7cilN64dG941IOXfhJhlH0qB92hxJ9A1ewrdUmJ6xo=
github.com/tonistiigi/fsutil v0.0.0-20220115021204-b19f7f9cb274/go.mod h1:oPAfvw32vlUJSjyDcQ3Bu0nb2ON2B+G0dtVN/SZNJiA=
github.com/tonistiigi/fsutil v0.0.0-20220315205639-9ed612626da3/go.mod h1:oPAfvw32vlUJSjyDcQ3Bu0nb2ON2B+G0dtVN/SZNJiA=
github.com/tonistiigi/fsutil v0.0.0-20220510150904-0dbf3a8a7d58 h1:rNya5ozLqz0lK46XhmsmqJuxmQLM8dAWabiT+5gZqLY=
github.com/tonistiigi/fsutil v0.0.0-20220510150904-0dbf3a8a7d58/go.mod h1:oPAfvw32vlUJSjyDcQ3Bu0nb2ON2B+G0dtVN/SZNJiA=
github.com/tonistiigi/fsutil v0.0.0-20220930225714-4638ad635be5 h1:NJ1nZs4j4XcBJKIY5sAwTGp9w5b78Zxr3+r0zXRuKnA=
github.com/tonistiigi/fsutil v0.0.0-20220930225714-4638ad635be5/go.mod h1:F83XRhNblQsKQH9hcKEE45GAOkL9590mtw9KsD0Q4fE=
github.com/tonistiigi/go-actions-cache v0.0.0-20211202175116-9642704158ff/go.mod h1:qqvyZqkfwkoJuPU/bw61bItaoO0SJ8YSW0vSVRRvsRg=
github.com/tonistiigi/go-actions-cache v0.0.0-20220404170428-0bdeb6e1eac7/go.mod h1:qqvyZqkfwkoJuPU/bw61bItaoO0SJ8YSW0vSVRRvsRg=
github.com/tonistiigi/go-archvariant v1.0.0/go.mod h1:TxFmO5VS6vMq2kvs3ht04iPXtu2rUT/erOnGFYfk5Ho=
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk=
@@ -1447,7 +1426,6 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
@@ -1490,13 +1468,10 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940 h1:p7OofyZ509h8DmPLh8Hn+EIIZm/xYhdZHJ9GnXHdr6U=
github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/gorelic v0.0.7 h1:4DTF1WOM2ZZS/xMOkTFBOcb6XiHu/PKn3rVo6dbewQE=
github.com/yvasiyarov/gorelic v0.0.7/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9 h1:AsFN8kXcCVkUFHyuzp1FtYbzp1nCO/H6+1uPSGEyPzM=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.4.0/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ=
github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
@@ -1526,14 +1501,15 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0=
go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 h1:n9b7AAdbQtQ0k9dm0Dm2/KUcUqtG8i2O15KzNaDze8c=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0/go.mod h1:LsankqVDx4W+RhZNA5uWarULII/MBhF5qwCYxTuyXjs=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0 h1:Wjp9vsVSIEyvdiaECfqxY9xBqQ7JaSCGtvHgR4doXZk=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0/go.mod h1:vHItvsnJtp7ES++nFLLFBzUWny7fJQSvTlxFcqQGUr4=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 h1:SLme4Porm+UwX0DdHMxlwRt7FzPSE0sys81bet2o0pU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0/go.mod h1:tLYsuf2v8fZreBVwp9gVMhefZlLFZaUiNVSq8QxXRII=
go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
@@ -1541,7 +1517,6 @@ go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtB
go.opentelemetry.io/otel v1.4.1 h1:QbINgGDDcoQUoMJa2mMaWno49lja9sHwp6aoa2n3a4g=
go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4=
go.opentelemetry.io/otel/exporters/jaeger v1.4.1/go.mod h1:ZW7vkOu9nC1CxsD8bHNHCia5JUbwP39vxgd1q4Z5rCI=
go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg=
go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
@@ -1552,8 +1527,10 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1/go.mod h1:c6E4V3/U+miqjs/8l950wggHGL1qzlp0Ypj9xoGrPqo=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1/go.mod h1:VwYo0Hak6Efuy0TXsZs8o1hnV3dHDPNtDbycG0hI8+M=
go.opentelemetry.io/otel/internal/metric v0.27.0 h1:9dAVGAfFiiEq5NVB9FUJ5et+btbDQAUIJehJ+ikyryk=
go.opentelemetry.io/otel/internal/metric v0.27.0/go.mod h1:n1CVxRqKqYZtqyTh9U/onvKapPGv7y/rpyOTI+LFNzw=
go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
go.opentelemetry.io/otel/metric v0.27.0 h1:HhJPsGhJoKRSegPQILFbODU56NS/L1UE4fS1sC5kIwQ=
go.opentelemetry.io/otel/metric v0.27.0/go.mod h1:raXDJ7uP2/Jc0nVZWQjJtzoyssOYWu/+pjZqRzfvZ7g=
go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
@@ -1611,12 +1588,12 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1656,6 +1633,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1724,9 +1703,14 @@ golang.org/x/net v0.0.0-20211005215030-d2e5035098b3/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1748,8 +1732,14 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 h1:B333XXssMuKQeBwiNODx4TupZy7bf4sxFZnN2ZOcvUE=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y=
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1882,18 +1872,28 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211004093028-2c5d950f24ef/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1903,8 +1903,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1912,8 +1913,9 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -2006,8 +2008,11 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0=
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
@@ -2049,8 +2054,19 @@ google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNe
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0 h1:4t9zuDlHLcIx0ZEhmXEeFVCRsiOgpgn2QOH9N0MNjPI=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
google.golang.org/api v0.84.0 h1:NMB9J4cCxs9xEm+1Z9QiO3eFvn7EnQj3Eo3hN6ugVlg=
google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -2113,6 +2129,7 @@ google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
@@ -2128,11 +2145,31 @@ google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEc
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 h1:Et6SkiuvnBn+SgrSYXs/BrUpGB4mbdwt4R3vaPIlicA=
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90 h1:4SPz2GL2CXJt28MTF8V6Ap/9ZiVbQlJeGSd9qtA7DLs=
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
@@ -2165,12 +2202,16 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -2184,8 +2225,9 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -2255,7 +2297,6 @@ k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs=
k8s.io/api v0.23.4/go.mod h1:i77F4JfyNNrhOjZF7OwwNJS5Y1S9dpwvb9iYRYRczfI=
k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8=
k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apimachinery v0.17.4/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g=
k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
@@ -2265,7 +2306,6 @@ k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MA
k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U=
k8s.io/apimachinery v0.23.4/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
k8s.io/apiserver v0.17.4/go.mod h1:5ZDQ6Xr5MNBxyi3iUZXS84QOhZl+W7Oq2us/29c0j9I=
k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
@@ -2279,7 +2319,6 @@ k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y=
k8s.io/client-go v0.23.4/go.mod h1:PKnIL4pqLuvYUK1WU7RLTMYKPiIh7MYShLshtRY9cj0=
k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4=
k8s.io/cloud-provider v0.17.4/go.mod h1:XEjKDzfD+b9MTLXQFlDGkk6Ho8SGMpaU8Uugx/KNK9U=
k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0=
@@ -2294,7 +2333,6 @@ k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4=
k8s.io/cri-api v0.24.0-alpha.3/go.mod h1:c/NLI5Zdyup5+oEYqFO2IE32ptofNiZpS1nL2y51gAg=
k8s.io/cri-api v0.24.0-beta.0/go.mod h1:t3tImFtGeStN+ES69bQUX9sFg67ek38BM9YIJhMmuig=
k8s.io/csi-translation-lib v0.17.4/go.mod h1:CsxmjwxEI0tTNMzffIAcgR9lX4wOh6AKHdxQrT7L0oo=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=

View File

@@ -9,14 +9,12 @@ import (
// drop-in 100% compatible replacement and 17% faster than compress/gzip.
gzip "github.com/klauspost/pgzip"
"github.com/linuxkit/linuxkit/src/cmd/linuxkit/pad4"
"github.com/surma/gocpio"
)
// Writer is an io.WriteCloser that writes to an initrd
// This is a compressed cpio archive, zero padded to 4 bytes
type Writer struct {
pw *pad4.Writer
gw *gzip.Writer
cw *cpio.Writer
}
@@ -136,8 +134,7 @@ func CopySplitTar(w *Writer, r *tar.Reader) (kernel []byte, cmdline string, ucod
// NewWriter creates a writer that will output an initrd stream
func NewWriter(w io.Writer) *Writer {
initrd := new(Writer)
initrd.pw = pad4.NewWriter(w)
initrd.gw = gzip.NewWriter(initrd.pw)
initrd.gw = gzip.NewWriter(w)
initrd.cw = cpio.NewWriter(initrd.gw)
return initrd
@@ -157,15 +154,11 @@ func (w *Writer) Write(b []byte) (n int, e error) {
func (w *Writer) Close() error {
err1 := w.cw.Close()
err2 := w.gw.Close()
err3 := w.pw.Close()
if err1 != nil {
return err1
}
if err2 != nil {
return err2
}
if err3 != nil {
return err3
}
return nil
}

View File

@@ -1,46 +0,0 @@
package pad4
import (
"bytes"
"io"
)
// A Writer is an io.WriteCloser. Writes are padded with zeros to 4 byte boundary
type Writer struct {
w io.Writer
count int
}
// Write writes output
func (pad *Writer) Write(p []byte) (int, error) {
n, err := pad.w.Write(p)
if err != nil {
return 0, err
}
pad.count += n
return n, nil
}
// Close adds the padding
func (pad *Writer) Close() error {
mod4 := pad.count & 3
if mod4 == 0 {
return nil
}
zero := make([]byte, 4-mod4)
buf := bytes.NewBuffer(zero)
n, err := io.Copy(pad.w, buf)
if err != nil {
return err
}
pad.count += int(n)
return nil
}
// NewWriter provides a new io.WriteCloser that zero pads the
// output to a multiple of four bytes
func NewWriter(w io.Writer) *Writer {
pad := new(Writer)
pad.w = w
return pad
}

View File

@@ -38,6 +38,7 @@ func pkgBuildPush(args []string, withPush bool) {
}
force := flags.Bool("force", false, "Force rebuild even if image is in local cache")
pull := flags.Bool("pull", false, "Pull image if in registry but not in local cache; conflicts with --force")
ignoreCache := flags.Bool("ignore-cached", false, "Ignore cached intermediate images, always pulling from registry")
docker := flags.Bool("docker", false, "Store the built image in the docker image cache instead of the default linuxkit cache")
platforms := flags.String("platforms", "", "Which platforms to build for, defaults to all of those for which the package can be built")
@@ -49,8 +50,10 @@ func pkgBuildPush(args []string, withPush bool) {
flags.Var(&cacheDir, "cache", fmt.Sprintf("Directory for caching and finding cached image, overrides env var %s", envVarCacheDir))
// some logic clarification:
// pkg build - always builds unless is in cache
// pkg build --force - always builds even if is in cache
// pkg build - builds unless is in cache or published in registry
// pkg build --pull - builds unless is in cache or published in registry; pulls from registry if not in cache
// pkg build --force - always builds even if is in cache or published in registry
// pkg build --force --pull - always builds even if is in cache or published in registry; --pull ignored
// pkg push - always builds unless is in cache
// pkg push --force - always builds even if is in cache
// pkg push --nobuild - skips build; if not in cache, fails
@@ -78,6 +81,10 @@ func pkgBuildPush(args []string, withPush bool) {
fmt.Fprint(os.Stderr, "flags -force and -nobuild conflict")
os.Exit(1)
}
if *pull && *force {
fmt.Fprint(os.Stderr, "flags -force and -pull conflict")
os.Exit(1)
}
var opts []pkglib.BuildOpt
if *force {
@@ -86,6 +93,9 @@ func pkgBuildPush(args []string, withPush bool) {
if *ignoreCache {
opts = append(opts, pkglib.WithBuildIgnoreCache())
}
if *pull {
opts = append(opts, pkglib.WithBuildPull())
}
opts = append(opts, pkglib.WithBuildCacheDir(cacheDir.String()))

View File

@@ -18,6 +18,7 @@ func pkgShowTag(args []string) {
fmt.Fprintf(os.Stderr, "\n")
flags.PrintDefaults()
}
canonical := flags.Bool("canonical", false, "Show canonical name, e.g. docker.io/linuxkit/foo:1234, instead of the default, e.g. linuxkit/foo:1234")
pkgs, err := pkglib.NewFromCLI(flags, args...)
if err != nil {
@@ -25,6 +26,10 @@ func pkgShowTag(args []string) {
os.Exit(1)
}
for _, p := range pkgs {
fmt.Println(p.Tag())
tag := p.Tag()
if *canonical {
tag = p.FullTag()
}
fmt.Println(tag)
}
}

View File

@@ -27,6 +27,7 @@ import (
type buildOpts struct {
skipBuild bool
force bool
pull bool
ignoreCache bool
push bool
release string
@@ -61,6 +62,14 @@ func WithBuildForce() BuildOpt {
}
}
// WithBuildPull pull down the image to cache if it already exists in registry
func WithBuildPull() BuildOpt {
return func(bo *buildOpts) error {
bo.pull = true
return nil
}
}
// WithBuildPush pushes the result of the build to the registry
func WithBuildPush() BuildOpt {
return func(bo *buildOpts) error {
@@ -89,6 +98,7 @@ func WithRelease(r string) BuildOpt {
func WithBuildTargetDockerCache() BuildOpt {
return func(bo *buildOpts) error {
bo.targetDocker = true
bo.pull = true // if we are to load it into docker, it must be in local cache
return nil
}
}
@@ -225,29 +235,61 @@ func (p Pkg) Build(bos ...BuildOpt) error {
}
var platformsToBuild []imagespec.Platform
if bo.force {
switch {
case bo.force && bo.skipBuild:
return errors.New("cannot force build and skip build")
case bo.force:
// force local build
platformsToBuild = bo.platforms
} else if !bo.skipBuild {
fmt.Fprintf(writer, "checking for %s in local cache, fallback to remote registry...\n", ref)
case bo.skipBuild:
// do not build anything if we explicitly did skipBuild
platformsToBuild = nil
default:
// check local cache, fallback to check registry / pull image from registry, fallback to build
fmt.Fprintf(writer, "checking for %s in local cache...\n", ref)
for _, platform := range bo.platforms {
if _, err := c.ImagePull(&ref, "", platform.Architecture, false); err == nil {
fmt.Fprintf(writer, "%s found or pulled\n", ref)
if bo.targetDocker {
archRef, err := reference.Parse(fmt.Sprintf("%s-%s", p.FullTag(), platform.Architecture))
if err != nil {
return err
}
fmt.Fprintf(writer, "checking for %s in local cache, fallback to remote registry...\n", archRef)
if _, err := c.ImagePull(&archRef, "", platform.Architecture, false); err == nil {
fmt.Fprintf(writer, "%s found or pulled\n", archRef)
} else {
fmt.Fprintf(writer, "%s not found, will build: %s\n", archRef, err)
platformsToBuild = append(platformsToBuild, platform)
if exists, err := c.ImageInCache(&ref, "", platform.Architecture); err == nil && exists {
fmt.Fprintf(writer, "found %s in local cache, skipping build\n", ref)
continue
}
if bo.pull {
// need to pull the image from the registry, else build
fmt.Fprintf(writer, "%s %s not found in local cache, trying to pull\n", ref, platform.Architecture)
if _, err := c.ImagePull(&ref, "", platform.Architecture, false); err == nil {
fmt.Fprintf(writer, "%s pulled\n", ref)
if bo.targetDocker {
archRef, err := reference.Parse(fmt.Sprintf("%s-%s", p.FullTag(), platform.Architecture))
if err != nil {
return err
}
fmt.Fprintf(writer, "checking for %s in local cache, fallback to remote registry...\n", archRef)
if _, err := c.ImagePull(&archRef, "", platform.Architecture, false); err == nil {
fmt.Fprintf(writer, "%s found or pulled\n", archRef)
} else {
fmt.Fprintf(writer, "%s not found, will build: %s\n", archRef, err)
platformsToBuild = append(platformsToBuild, platform)
}
}
// successfully pulled, no need to build, continue with next platform
continue
}
} else {
fmt.Fprintf(writer, "%s not found, will build: %s\n", ref, err)
platformsToBuild = append(platformsToBuild, platform)
} else {
// do not pull, just check if it exists in a registry
fmt.Fprintf(writer, "%s %s not found in local cache, checking registry\n", ref, platform.Architecture)
exists, err := c.ImageInRegistry(&ref, "", platform.Architecture)
if err != nil {
return fmt.Errorf("error checking remote registry for %s: %v", ref, err)
}
if exists {
fmt.Fprintf(writer, "%s %s found on registry\n", ref, platform.Architecture)
continue
}
fmt.Fprintf(writer, "%s %s not found, will build\n", ref, platform.Architecture)
platformsToBuild = append(platformsToBuild, platform)
}
}
}
@@ -282,6 +324,7 @@ func (p Pkg) Build(bos ...BuildOpt) error {
imageBuildOpts.Labels["org.opencontainers.image.revision"] = commit
}
imageBuildOpts.NetworkMode = "default"
if !p.network {
imageBuildOpts.NetworkMode = "none"
}
@@ -316,6 +359,9 @@ func (p Pkg) Build(bos ...BuildOpt) error {
if desc == nil {
return fmt.Errorf("no valid descriptor returned for image for arch %s", platform.Architecture)
}
if desc.Platform == nil {
return fmt.Errorf("descriptor for platform %v has no information on the platform: %#v", platform, desc)
}
descs = append(descs, *desc)
}

View File

@@ -112,6 +112,24 @@ func (c *cacheMocker) ImagePull(ref *reference.Spec, trustedRef, architecture st
return c.imageWriteStream(ref, architecture, bytes.NewReader(b))
}
func (c *cacheMocker) ImageInCache(ref *reference.Spec, trustedRef, architecture string) (bool, error) {
image := ref.String()
desc, ok := c.images[image]
if !ok {
return false, nil
}
for _, d := range desc {
if d.Platform != nil && d.Platform.Architecture == architecture {
return true, nil
}
}
return false, nil
}
func (c *cacheMocker) ImageInRegistry(ref *reference.Spec, trustedRef, architecture string) (bool, error) {
return false, nil
}
func (c *cacheMocker) ImageLoad(ref *reference.Spec, architecture string, r io.Reader) (lktspec.ImageSource, error) {
if !c.enableImageLoad {
return nil, errors.New("ImageLoad disabled")

View File

@@ -432,7 +432,15 @@ func (dr *dockerRunnerImpl) build(ctx context.Context, tag, pkg, dockerContext,
}
// network
frontendAttrs["network"] = imageBuildOpts.NetworkMode
// translate to net modes understood by buildkit dockerfile frontend
switch imageBuildOpts.NetworkMode {
case "host", "none":
frontendAttrs["force-network-mode"] = imageBuildOpts.NetworkMode
case "default":
frontendAttrs["force-network-mode"] = "sandbox"
default:
return fmt.Errorf("unsupported network mode %q", imageBuildOpts.NetworkMode)
}
for k, v := range imageBuildOpts.Labels {
frontendAttrs[fmt.Sprintf("label:%s", k)] = v

View File

@@ -16,7 +16,7 @@ import (
"strings"
"syscall"
"github.com/Code-Hex/vz"
vz "github.com/Code-Hex/vz/v3"
"github.com/pkg/term/termios"
log "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
@@ -147,22 +147,34 @@ func runVirtualizationFramework(args []string) {
}
vmlinuzFile = vmlinuzUncompressed
}
bootLoader := vz.NewLinuxBootLoader(
bootLoader, err := vz.NewLinuxBootLoader(
vmlinuzFile,
vz.WithCommandLine(strings.Join(kernelCommandLineArguments, " ")),
vz.WithInitrd(initrd),
)
if err != nil {
log.Fatalf("unable to create bootloader: %v", err)
}
config := vz.NewVirtualMachineConfiguration(
config, err := vz.NewVirtualMachineConfiguration(
bootLoader,
*cpus,
memBytes,
)
if err != nil {
log.Fatalf("unable to create VM config: %v", err)
}
// console
stdin, stdout := os.Stdin, os.Stdout
serialPortAttachment := vz.NewFileHandleSerialPortAttachment(stdin, stdout)
consoleConfig := vz.NewVirtioConsoleDeviceSerialPortConfiguration(serialPortAttachment)
serialPortAttachment, err := vz.NewFileHandleSerialPortAttachment(stdin, stdout)
if err != nil {
log.Fatalf("unable to create serial port attachment: %v", err)
}
consoleConfig, err := vz.NewVirtioConsoleDeviceSerialPortConfiguration(serialPortAttachment)
if err != nil {
log.Fatalf("unable to create console config: %v", err)
}
config.SetSerialPortsVirtualMachineConfiguration([]*vz.VirtioConsoleDeviceSerialPortConfiguration{
consoleConfig,
})
@@ -179,19 +191,33 @@ func runVirtualizationFramework(args []string) {
switch netMode[0] {
case virtualizationNetworkingVMNet:
natAttachment := vz.NewNATNetworkDeviceAttachment()
networkConfig := vz.NewVirtioNetworkDeviceConfiguration(natAttachment)
natAttachment, err := vz.NewNATNetworkDeviceAttachment()
if err != nil {
log.Fatalf("Could not create NAT network device attachment: %v", err)
}
networkConfig, err := vz.NewVirtioNetworkDeviceConfiguration(natAttachment)
if err != nil {
log.Fatalf("Could not create virtio network device configuration: %v", err)
}
config.SetNetworkDevicesVirtualMachineConfiguration([]*vz.VirtioNetworkDeviceConfiguration{
networkConfig,
})
networkConfig.SetMacAddress(vz.NewRandomLocallyAdministeredMACAddress())
macAddress, err := vz.NewRandomLocallyAdministeredMACAddress()
if err != nil {
log.Fatalf("Could not create random MAC address: %v", err)
}
networkConfig.SetMACAddress(macAddress)
case virtualizationNetworkingNone:
default:
log.Fatalf("Invalid networking mode: %s", netMode[0])
}
// entropy
entropyConfig := vz.NewVirtioEntropyDeviceConfiguration()
entropyConfig, err := vz.NewVirtioEntropyDeviceConfiguration()
if err != nil {
log.Fatalf("Could not create virtio entropy device configuration: %v", err)
}
config.SetEntropyDevicesVirtualMachineConfiguration([]*vz.VirtioEntropyDeviceConfiguration{
entropyConfig,
})
@@ -215,7 +241,10 @@ func runVirtualizationFramework(args []string) {
if err != nil {
log.Fatal(err)
}
storageDeviceConfig := vz.NewVirtioBlockDeviceConfiguration(diskImageAttachment)
storageDeviceConfig, err := vz.NewVirtioBlockDeviceConfiguration(diskImageAttachment)
if err != nil {
log.Fatalf("Could not create virtio block device configuration: %v", err)
}
storageDevices = append(storageDevices, storageDeviceConfig)
}
for _, iso := range isoPaths {
@@ -226,38 +255,50 @@ func runVirtualizationFramework(args []string) {
if err != nil {
log.Fatal(err)
}
storageDeviceConfig := vz.NewVirtioBlockDeviceConfiguration(diskImageAttachment)
storageDeviceConfig, err := vz.NewVirtioBlockDeviceConfiguration(diskImageAttachment)
if err != nil {
log.Fatalf("Could not create virtio block device configuration: %v", err)
}
storageDevices = append(storageDevices, storageDeviceConfig)
}
config.SetStorageDevicesVirtualMachineConfiguration(storageDevices)
// traditional memory balloon device which allows for managing guest memory. (optional)
memoryBalloonDeviceConfiguration, err := vz.NewVirtioTraditionalMemoryBalloonDeviceConfiguration()
if err != nil {
log.Fatalf("Could not create virtio traditional memory balloon device configuration: %v", err)
}
config.SetMemoryBalloonDevicesVirtualMachineConfiguration([]vz.MemoryBalloonDeviceConfiguration{
vz.NewVirtioTraditionalMemoryBalloonDeviceConfiguration(),
memoryBalloonDeviceConfiguration,
})
// socket device (optional)
socketDeviceConfiguration, err := vz.NewVirtioSocketDeviceConfiguration()
if err != nil {
log.Fatalf("Could not create virtio socket device configuration: %v", err)
}
config.SetSocketDevicesVirtualMachineConfiguration([]vz.SocketDeviceConfiguration{
vz.NewVirtioSocketDeviceConfiguration(),
socketDeviceConfiguration,
})
validated, err := config.Validate()
if !validated || err != nil {
log.Fatal("validation failed", err)
}
vm := vz.NewVirtualMachine(config)
vm, err := vz.NewVirtualMachine(config)
if err != nil {
log.Fatalf("Could not create virtual machine: %v", err)
}
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, syscall.SIGTERM)
errCh := make(chan error, 1)
vm.Start(func(err error) {
if err != nil {
errCh <- err
}
})
if err := vm.Start(); err != nil {
errCh <- err
}
for {
select {

View File

@@ -20,6 +20,12 @@ type CacheProvider interface {
// efficient and only write missing blobs, based on their content hash. If the ref already
// exists in the cache, it should not pull anything, unless alwaysPull is set to true.
ImagePull(ref *reference.Spec, trustedRef, architecture string, alwaysPull bool) (ImageSource, error)
// ImageInCache takes an image name and checks if it exists in the cache, including checking that the given
// architecture is complete. Like ImagePull, it should be efficient and only write missing blobs, based on
// their content hash.
ImageInCache(ref *reference.Spec, trustedRef, architecture string) (bool, error)
// ImageInRegistry takes an image name and checks if it exists in the registry.
ImageInRegistry(ref *reference.Spec, trustedRef, architecture string) (bool, error)
// IndexWrite takes an image name and creates an index for the descriptors to which it points.
// Cache implementation determines whether it should pull missing blobs from a remote registry.
// If the provided reference already exists and it is an index, updates the manifests in the

View File

@@ -16,7 +16,7 @@
// metadata and API service accounts.
//
// This package is a wrapper around the GCE metadata service,
// as documented at https://developers.google.com/compute/docs/metadata.
// as documented at https://cloud.google.com/compute/docs/metadata/overview.
package metadata // import "cloud.google.com/go/compute/metadata"
import (
@@ -61,14 +61,18 @@ var (
instID = &cachedValue{k: "instance/id", trim: true}
)
var defaultClient = &Client{hc: &http.Client{
Transport: &http.Transport{
Dial: (&net.Dialer{
Timeout: 2 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
},
}}
var defaultClient = &Client{hc: newDefaultHTTPClient()}
func newDefaultHTTPClient() *http.Client {
return &http.Client{
Transport: &http.Transport{
Dial: (&net.Dialer{
Timeout: 2 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
},
}
}
// NotDefinedError is returned when requested metadata is not defined.
//
@@ -130,7 +134,7 @@ func testOnGCE() bool {
go func() {
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
req.Header.Set("User-Agent", userAgent)
res, err := defaultClient.hc.Do(req.WithContext(ctx))
res, err := newDefaultHTTPClient().Do(req.WithContext(ctx))
if err != nil {
resc <- false
return
@@ -140,7 +144,8 @@ func testOnGCE() bool {
}()
go func() {
addrs, err := net.DefaultResolver.LookupHost(ctx, "metadata.google.internal")
resolver := &net.Resolver{}
addrs, err := resolver.LookupHost(ctx, "metadata.google.internal")
if err != nil || len(addrs) == 0 {
resc <- false
return
@@ -323,7 +328,7 @@ func (c *Client) getETag(suffix string) (value, etag string, err error) {
break
}
if reqErr != nil {
return "", "", nil
return "", "", reqErr
}
defer res.Body.Close()
if res.StatusCode == http.StatusNotFound {

View File

@@ -1,5 +0,0 @@
module github.com/Azure/go-ansiterm
go 1.16
require golang.org/x/sys v0.0.0-20210616094352-59db8d763f22

View File

@@ -1,2 +0,0 @@
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@@ -1,13 +0,0 @@
module github.com/Azure/go-autorest/autorest/adal
go 1.15
require (
github.com/Azure/go-autorest v14.2.0+incompatible
github.com/Azure/go-autorest/autorest/date v0.3.0
github.com/Azure/go-autorest/autorest/mocks v0.4.1
github.com/Azure/go-autorest/logger v0.2.1
github.com/Azure/go-autorest/tracing v0.6.0
github.com/golang-jwt/jwt/v4 v4.0.0
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
)

View File

@@ -1,20 +0,0 @@
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -1,5 +0,0 @@
module github.com/Azure/go-autorest/autorest/date
go 1.12
require github.com/Azure/go-autorest v14.2.0+incompatible

View File

@@ -1,2 +0,0 @@
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=

View File

@@ -1,13 +0,0 @@
module github.com/Azure/go-autorest/autorest
go 1.15
require (
github.com/Azure/go-autorest v14.2.0+incompatible
github.com/Azure/go-autorest/autorest/adal v0.9.18
github.com/Azure/go-autorest/autorest/mocks v0.4.1
github.com/Azure/go-autorest/logger v0.2.1
github.com/Azure/go-autorest/tracing v0.6.0
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
)

View File

@@ -1,27 +0,0 @@
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ=
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -1,5 +0,0 @@
module github.com/Azure/go-autorest/autorest/to
go 1.12
require github.com/Azure/go-autorest v14.2.0+incompatible

View File

@@ -1,2 +0,0 @@
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=

View File

@@ -1,8 +0,0 @@
module github.com/Azure/go-autorest/autorest/validation
go 1.12
require (
github.com/Azure/go-autorest v14.2.0+incompatible
github.com/stretchr/testify v1.3.0
)

View File

@@ -1,9 +0,0 @@
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=

View File

@@ -1,5 +0,0 @@
module github.com/Azure/go-autorest/logger
go 1.12
require github.com/Azure/go-autorest v14.2.0+incompatible

View File

@@ -1,2 +0,0 @@
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=

View File

@@ -1,5 +0,0 @@
module github.com/Azure/go-autorest/tracing
go 1.12
require github.com/Azure/go-autorest v14.2.0+incompatible

View File

@@ -1,2 +0,0 @@
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=

View File

@@ -1,2 +0,0 @@
virtualization
*.log

View File

@@ -1,52 +0,0 @@
vz - Go binding with Apple [Virtualization.framework](https://developer.apple.com/documentation/virtualization?language=objc)
=======
vz provides the power of the Apple Virtualization.framework in Go. Put here is block quote of overreview which is written what is Virtualization.framework from the document.
> The Virtualization framework provides high-level APIs for creating and managing virtual machines on Apple silicon and Intel-based Mac computers. Use this framework to boot and run a Linux-based operating system in a custom environment that you define. The framework supports the Virtio specification, which defines standard interfaces for many device types, including network, socket, serial port, storage, entropy, and memory-balloon devices.
## USAGE
Please see the example directory.
## REQUIREMENTS
- Higher or equal to macOS Big Sur (11.0.0)
- If you're M1 Mac User need higher or equal to Go 1.16
## IMPORTANT
For binaries used in this package, you need to create an entitlements file like the one below and apply the following command.
<details>
<summary>vz.entitlements</summary>
```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.virtualization</key>
<true/>
</dict>
</plist>
```
</details>
```sh
$ codesign --entitlements vz.entitlements -s - <YOUR BINARY PATH>
```
> A process must have the com.apple.security.virtualization entitlement to use the Virtualization APIs.
If you want to use [`VZBridgedNetworkDeviceAttachment`](https://developer.apple.com/documentation/virtualization/vzbridgednetworkdeviceattachment?language=objc), you need to add also `com.apple.vm.networking` entitlement.
## TODO
- [x] [VZMACAddress](https://developer.apple.com/documentation/virtualization/vzmacaddress?language=objc)
- [ ] [VZVirtioSocketDeviceConfiguration](https://developer.apple.com/documentation/virtualization/sockets?language=objc)
## LICENSE
MIT License

View File

@@ -1,89 +0,0 @@
package vz
/*
#cgo darwin CFLAGS: -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization.h"
*/
import "C"
import (
"fmt"
"runtime"
)
// BootLoader is the interface of boot loader definitions.
// see: LinuxBootLoader
type BootLoader interface {
NSObject
bootLoader()
}
type baseBootLoader struct{}
func (*baseBootLoader) bootLoader() {}
var _ BootLoader = (*LinuxBootLoader)(nil)
// LinuxBootLoader Boot loader configuration for a Linux kernel.
type LinuxBootLoader struct {
vmlinuzPath string
initrdPath string
cmdLine string
pointer
*baseBootLoader
}
func (b *LinuxBootLoader) String() string {
return fmt.Sprintf(
"vmlinuz: %q, initrd: %q, command-line: %q",
b.vmlinuzPath,
b.initrdPath,
b.cmdLine,
)
}
type LinuxBootLoaderOption func(b *LinuxBootLoader)
// WithCommandLine sets the command-line parameters.
// see: https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
func WithCommandLine(cmdLine string) LinuxBootLoaderOption {
return func(b *LinuxBootLoader) {
b.cmdLine = cmdLine
cs := charWithGoString(cmdLine)
defer cs.Free()
C.setCommandLineVZLinuxBootLoader(b.Ptr(), cs.CString())
}
}
// WithInitrd sets the optional initial RAM disk.
func WithInitrd(initrdPath string) LinuxBootLoaderOption {
return func(b *LinuxBootLoader) {
b.initrdPath = initrdPath
cs := charWithGoString(initrdPath)
defer cs.Free()
C.setInitialRamdiskURLVZLinuxBootLoader(b.Ptr(), cs.CString())
}
}
// NewLinuxBootLoader creates a LinuxBootLoader with the Linux kernel passed as Path.
func NewLinuxBootLoader(vmlinuz string, opts ...LinuxBootLoaderOption) *LinuxBootLoader {
vmlinuzPath := charWithGoString(vmlinuz)
defer vmlinuzPath.Free()
bootLoader := &LinuxBootLoader{
vmlinuzPath: vmlinuz,
pointer: pointer{
ptr: C.newVZLinuxBootLoader(
vmlinuzPath.CString(),
),
},
}
runtime.SetFinalizer(bootLoader, func(self *LinuxBootLoader) {
self.Release()
})
for _, opt := range opts {
opt(bootLoader)
}
return bootLoader
}

View File

@@ -1,137 +0,0 @@
package vz
/*
#cgo darwin CFLAGS: -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization.h"
*/
import "C"
import "runtime"
// VirtualMachineConfiguration defines the configuration of a VirtualMachine.
//
// The following properties must be configured before creating a virtual machine:
// - bootLoader
//
// The configuration of devices is often done in two parts:
// - Device configuration
// - Device attachment
//
// The device configuration defines the characteristics of the emulated hardware device.
// For example, for a network device, the device configuration defines the type of network adapter present
// in the virtual machine and its MAC address.
//
// The device attachment defines the host machine's resources that are exposed by the virtual device.
// For example, for a network device, the device attachment can be virtual network interface with a NAT
// to the real network.
//
// Creating a virtual machine using the Virtualization framework requires the app to have the "com.apple.security.virtualization" entitlement.
// A VirtualMachineConfiguration is considered invalid if the application does not have the entitlement.
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtualmachineconfiguration?language=objc
type VirtualMachineConfiguration struct {
cpuCount uint
memorySize uint64
pointer
}
// NewVirtualMachineConfiguration creates a new configuration.
//
// - bootLoader parameter is used when the virtual machine starts.
// - cpu parameter is The number of CPUs must be a value between
// VZVirtualMachineConfiguration.minimumAllowedCPUCount and VZVirtualMachineConfiguration.maximumAllowedCPUCount.
// - memorySize parameter represents memory size in bytes.
// The memory size must be a multiple of a 1 megabyte (1024 * 1024 bytes) between
// VZVirtualMachineConfiguration.minimumAllowedMemorySize and VZVirtualMachineConfiguration.maximumAllowedMemorySize.
func NewVirtualMachineConfiguration(bootLoader BootLoader, cpu uint, memorySize uint64) *VirtualMachineConfiguration {
config := &VirtualMachineConfiguration{
cpuCount: cpu,
memorySize: memorySize,
pointer: pointer{
ptr: C.newVZVirtualMachineConfiguration(
bootLoader.Ptr(),
C.uint(cpu),
C.ulonglong(memorySize),
),
},
}
runtime.SetFinalizer(config, func(self *VirtualMachineConfiguration) {
self.Release()
})
return config
}
// Validate the configuration.
//
// Return true if the configuration is valid.
// If error is not nil, assigned with the validation error if the validation failed.
func (v *VirtualMachineConfiguration) Validate() (bool, error) {
nserr := newNSErrorAsNil()
nserrPtr := nserr.Ptr()
ret := C.validateVZVirtualMachineConfiguration(v.Ptr(), &nserrPtr)
err := newNSError(nserrPtr)
if err != nil {
return false, err
}
return (bool)(ret), nil
}
// SetEntropyDevicesVirtualMachineConfiguration sets list of entropy devices. Empty by default.
func (v *VirtualMachineConfiguration) SetEntropyDevicesVirtualMachineConfiguration(cs []*VirtioEntropyDeviceConfiguration) {
ptrs := make([]NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := convertToNSMutableArray(ptrs)
C.setEntropyDevicesVZVirtualMachineConfiguration(v.Ptr(), array.Ptr())
}
// SetMemoryBalloonDevicesVirtualMachineConfiguration sets list of memory balloon devices. Empty by default.
func (v *VirtualMachineConfiguration) SetMemoryBalloonDevicesVirtualMachineConfiguration(cs []MemoryBalloonDeviceConfiguration) {
ptrs := make([]NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := convertToNSMutableArray(ptrs)
C.setMemoryBalloonDevicesVZVirtualMachineConfiguration(v.Ptr(), array.Ptr())
}
// SetNetworkDevicesVirtualMachineConfiguration sets list of network adapters. Empty by default.
func (v *VirtualMachineConfiguration) SetNetworkDevicesVirtualMachineConfiguration(cs []*VirtioNetworkDeviceConfiguration) {
ptrs := make([]NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := convertToNSMutableArray(ptrs)
C.setNetworkDevicesVZVirtualMachineConfiguration(v.Ptr(), array.Ptr())
}
// SetSerialPortsVirtualMachineConfiguration sets list of serial ports. Empty by default.
func (v *VirtualMachineConfiguration) SetSerialPortsVirtualMachineConfiguration(cs []*VirtioConsoleDeviceSerialPortConfiguration) {
ptrs := make([]NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := convertToNSMutableArray(ptrs)
C.setSerialPortsVZVirtualMachineConfiguration(v.Ptr(), array.Ptr())
}
// SetSocketDevicesVirtualMachineConfiguration sets list of socket devices. Empty by default.
func (v *VirtualMachineConfiguration) SetSocketDevicesVirtualMachineConfiguration(cs []SocketDeviceConfiguration) {
ptrs := make([]NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := convertToNSMutableArray(ptrs)
C.setSocketDevicesVZVirtualMachineConfiguration(v.Ptr(), array.Ptr())
}
// SetStorageDevicesVirtualMachineConfiguration sets list of disk devices. Empty by default.
func (v *VirtualMachineConfiguration) SetStorageDevicesVirtualMachineConfiguration(cs []StorageDeviceConfiguration) {
ptrs := make([]NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := convertToNSMutableArray(ptrs)
C.setStorageDevicesVZVirtualMachineConfiguration(v.Ptr(), array.Ptr())
}

View File

@@ -1,5 +0,0 @@
module github.com/Code-Hex/vz
go 1.16
require github.com/rs/xid v1.2.1

View File

@@ -1,2 +0,0 @@
github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=

View File

@@ -1,206 +0,0 @@
package vz
/*
#cgo darwin CFLAGS: -x objective-c
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization.h"
const char *getNSErrorLocalizedDescription(void *err)
{
NSString *ld = (NSString *)[(NSError *)err localizedDescription];
return [ld UTF8String];
}
const char *getNSErrorDomain(void *err)
{
const char *ret;
@autoreleasepool {
NSString *domain = (NSString *)[(NSError *)err domain];
ret = [domain UTF8String];
}
return ret;
}
const char *getNSErrorUserInfo(void *err)
{
NSDictionary<NSErrorUserInfoKey, id> *ui = [(NSError *)err userInfo];
NSString *uis = [NSString stringWithFormat:@"%@", ui];
return [uis UTF8String];
}
NSInteger getNSErrorCode(void *err)
{
return (NSInteger)[(NSError *)err code];
}
void *makeNSMutableArray(unsigned long cap)
{
return [[NSMutableArray alloc] initWithCapacity:(NSUInteger)cap];
}
void addNSMutableArrayVal(void *ary, void *val)
{
[(NSMutableArray *)ary addObject:(NSObject *)val];
}
void *newNSError()
{
NSError *err = nil;
return err;
}
bool hasError(void *err)
{
return (NSError *)err != nil;
}
void *minimumAlloc()
{
return [[NSMutableData dataWithLength:1] mutableBytes];
}
void releaseNSObject(void* o)
{
@autoreleasepool {
[(NSObject*)o release];
}
}
static inline void startNSThread()
{
[[NSThread new] start]; // put the runtime into multi-threaded mode
}
static inline void releaseDispatch(void *queue)
{
dispatch_release((dispatch_queue_t)queue);
}
*/
import "C"
import (
"fmt"
"runtime"
"unsafe"
)
// startNSThread starts NSThread.
func startNSThread() {
C.startNSThread()
}
// releaseDispatch releases allocated dispatch_queue_t
func releaseDispatch(p unsafe.Pointer) {
C.releaseDispatch(p)
}
// CharWithGoString makes *Char which is *C.Char wrapper from Go string.
func charWithGoString(s string) *char {
return (*char)(unsafe.Pointer(C.CString(s)))
}
// Char is a wrapper of C.char
type char C.char
// CString converts *C.char from *Char
func (c *char) CString() *C.char {
return (*C.char)(c)
}
// String converts Go string from *Char
func (c *char) String() string {
return C.GoString((*C.char)(c))
}
// Free frees allocated *C.char in Go code
func (c *char) Free() {
C.free(unsafe.Pointer(c))
}
// pointer indicates any pointers which are allocated in objective-c world.
type pointer struct {
ptr unsafe.Pointer
}
// Release releases allocated resources in objective-c world.
func (p *pointer) Release() {
C.releaseNSObject(p.Ptr())
runtime.KeepAlive(p)
}
// Ptr returns raw pointer.
func (o *pointer) Ptr() unsafe.Pointer {
if o == nil {
return nil
}
return o.ptr
}
// NSObject indicates NSObject
type NSObject interface {
Ptr() unsafe.Pointer
}
// NSError indicates NSError.
type NSError struct {
Domain string
Code int
LocalizedDescription string
UserInfo string
pointer
}
// newNSErrorAsNil makes nil NSError in objective-c world.
func newNSErrorAsNil() *pointer {
p := &pointer{
ptr: unsafe.Pointer(C.newNSError()),
}
return p
}
// hasNSError checks passed pointer is NSError or not.
func hasNSError(nserrPtr unsafe.Pointer) bool {
return (bool)(C.hasError(nserrPtr))
}
func (n *NSError) Error() string {
if n == nil {
return "<nil>"
}
return fmt.Sprintf(
"Error Domain=%s Code=%d Description=%q UserInfo=%s",
n.Domain,
n.Code,
n.LocalizedDescription,
n.UserInfo,
)
}
// TODO(codehex): improvement (3 times called C functions now)
func newNSError(p unsafe.Pointer) *NSError {
if !hasNSError(p) {
return nil
}
domain := (*char)(C.getNSErrorDomain(p))
description := (*char)(C.getNSErrorLocalizedDescription(p))
userInfo := (*char)(C.getNSErrorUserInfo(p))
return &NSError{
Domain: domain.String(),
Code: int(C.getNSErrorCode(p)),
LocalizedDescription: description.String(),
UserInfo: userInfo.String(), // NOTE(codehex): maybe we can convert to map[string]interface{}
}
}
// convertToNSMutableArray converts to NSMutableArray from NSObject slice in Go world.
func convertToNSMutableArray(s []NSObject) *pointer {
ln := len(s)
ary := C.makeNSMutableArray(C.ulong(ln))
for _, v := range s {
C.addNSMutableArrayVal(ary, v.Ptr())
}
p := &pointer{ptr: ary}
runtime.SetFinalizer(p, func(self *pointer) {
self.Release()
})
return p
}

View File

@@ -1,46 +0,0 @@
package vz
/*
#cgo darwin CFLAGS: -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization.h"
*/
import "C"
import "runtime"
// SocketDeviceConfiguration for a socket device configuration.
type SocketDeviceConfiguration interface {
NSObject
socketDeviceConfiguration()
}
type baseSocketDeviceConfiguration struct{}
func (*baseSocketDeviceConfiguration) socketDeviceConfiguration() {}
var _ SocketDeviceConfiguration = (*VirtioSocketDeviceConfiguration)(nil)
// VirtioSocketDeviceConfiguration is a configuration of the Virtio socket device.
//
// This configuration creates a Virtio socket device for the guest which communicates with the host through the Virtio interface.
// Only one Virtio socket device can be used per virtual machine.
// see: https://developer.apple.com/documentation/virtualization/vzvirtiosocketdeviceconfiguration?language=objc
type VirtioSocketDeviceConfiguration struct {
pointer
*baseSocketDeviceConfiguration
}
// NewVirtioSocketDeviceConfiguration creates a new VirtioSocketDeviceConfiguration.
func NewVirtioSocketDeviceConfiguration() *VirtioSocketDeviceConfiguration {
config := &VirtioSocketDeviceConfiguration{
pointer: pointer{
ptr: C.newVZVirtioSocketDeviceConfiguration(),
},
}
runtime.SetFinalizer(config, func(self *VirtioSocketDeviceConfiguration) {
self.Release()
})
return config
}

View File

@@ -1,109 +0,0 @@
package vz
/*
#cgo darwin CFLAGS: -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization.h"
*/
import "C"
import "runtime"
type baseStorageDeviceAttachment struct{}
func (*baseStorageDeviceAttachment) storageDeviceAttachment() {}
// StorageDeviceAttachment for a storage device attachment.
//
// A storage device attachment defines how a virtual machine storage device interfaces with the host system.
// see: https://developer.apple.com/documentation/virtualization/vzstoragedeviceattachment?language=objc
type StorageDeviceAttachment interface {
NSObject
storageDeviceAttachment()
}
var _ StorageDeviceAttachment = (*DiskImageStorageDeviceAttachment)(nil)
// DiskImageStorageDeviceAttachment is a storage device attachment using a disk image to implement the storage.
//
// This storage device attachment uses a disk image on the host file system as the drive of the storage device.
// Only raw data disk images are supported.
// see: https://developer.apple.com/documentation/virtualization/vzdiskimagestoragedeviceattachment?language=objc
type DiskImageStorageDeviceAttachment struct {
pointer
*baseStorageDeviceAttachment
}
// NewDiskImageStorageDeviceAttachment 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.
func NewDiskImageStorageDeviceAttachment(diskPath string, readOnly bool) (*DiskImageStorageDeviceAttachment, error) {
nserr := newNSErrorAsNil()
nserrPtr := nserr.Ptr()
diskPathChar := charWithGoString(diskPath)
defer diskPathChar.Free()
attachment := &DiskImageStorageDeviceAttachment{
pointer: pointer{
ptr: C.newVZDiskImageStorageDeviceAttachment(
diskPathChar.CString(),
C.bool(readOnly),
&nserrPtr,
),
},
}
if err := newNSError(nserrPtr); err != nil {
return nil, err
}
runtime.SetFinalizer(attachment, func(self *DiskImageStorageDeviceAttachment) {
self.Release()
})
return attachment, nil
}
// StorageDeviceConfiguration for a storage device configuration.
type StorageDeviceConfiguration interface {
NSObject
storageDeviceConfiguration()
}
type baseStorageDeviceConfiguration struct{}
func (*baseStorageDeviceConfiguration) storageDeviceConfiguration() {}
var _ StorageDeviceConfiguration = (*VirtioBlockDeviceConfiguration)(nil)
// VirtioBlockDeviceConfiguration is a configuration of a paravirtualized storage device of type Virtio Block Device.
//
// This device configuration creates a storage device using paravirtualization.
// The emulated device follows the Virtio Block Device specification.
//
// The host implementation of the device is done through an attachment subclassing VZStorageDeviceAttachment
// like VZDiskImageStorageDeviceAttachment.
// see: https://developer.apple.com/documentation/virtualization/vzvirtioblockdeviceconfiguration?language=objc
type VirtioBlockDeviceConfiguration struct {
pointer
*baseStorageDeviceConfiguration
}
// NewVirtioBlockDeviceConfiguration initialize a VZVirtioBlockDeviceConfiguration with a device attachment.
//
// - attachment The storage device attachment. This defines how the virtualized device operates on the host side.
func NewVirtioBlockDeviceConfiguration(attachment StorageDeviceAttachment) *VirtioBlockDeviceConfiguration {
config := &VirtioBlockDeviceConfiguration{
pointer: pointer{
ptr: C.newVZVirtioBlockDeviceConfiguration(
attachment.Ptr(),
),
},
}
runtime.SetFinalizer(config, func(self *VirtioBlockDeviceConfiguration) {
self.Release()
})
return config
}

View File

@@ -0,0 +1,4 @@
BasedOnStyle: WebKit
Language: ObjC
TabWidth: 4
PointerAlignment: Right

View File

@@ -0,0 +1,7 @@
virtualization
*.log
.envrc
.env
RestoreImage.ipsw
testdata/*
!testdata/.gitkeep

View File

@@ -0,0 +1,23 @@
## How to contribute to github.com/Code-Hex/vz
#### **Did you find a bug?**
* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/Code-Hex/vz/issues).
* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/Code-Hex/vz/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
#### **Did you write a patch that fixes a bug?**
* Open a new GitHub pull request with the patch.
* Ensure the PR description clearly describes the problem and solution. **Must** be included the relevant issue number.
> **Note**
> Basically, this can be done after a policy has been decided like how to write the code or how to implement, etc in an issue.
> **Warning**
> We generally do not accept some pull requests like either did not follow the owner's opinion or harassing.
#### **Did you fix whitespace, format code, or make a purely cosmetic patch?**
Changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability of github.com/Code-Hex/vz will generally not be accepted.

View File

@@ -0,0 +1,31 @@
PUIPUI_LINUX_VERSION := 0.0.1
ARCH := $(shell uname -m)
KERNEL_ARCH := $(shell echo $(ARCH) | sed -e s/arm64/aarch64/)
KERNEL_TAR := puipui_linux_v$(PUIPUI_LINUX_VERSION)_$(KERNEL_ARCH).tar.gz
KERNEL_DOWNLOAD_URL := https://github.com/Code-Hex/puipui-linux/releases/download/v$(PUIPUI_LINUX_VERSION)/$(KERNEL_TAR)
.PHONY: fmt
fmt:
@ls | grep -E '\.(h|m)$$' | xargs clang-format -i --verbose
.PHONY: test
test:
go test -exec "go run $(PWD)/cmd/codesign" ./... -timeout 60s -v
.PHONY: download_kernel
download_kernel:
curl --output-dir testdata -LO $(KERNEL_DOWNLOAD_URL)
@tar xvf testdata/$(KERNEL_TAR) -C testdata
ifeq ($(ARCH),arm64)
@gunzip -f testdata/Image.gz
else
@mv testdata/bzImage testdata/Image
endif
.PHONY: install/stringer
install/stringer:
@go install golang.org/x/tools/cmd/stringer@latest
.PHONY: clean
clean:
@rm testdata/{Image,initramfs.cpio.gz,*.tar.gz}

View File

@@ -0,0 +1,137 @@
vz - Go binding with Apple [Virtualization.framework](https://developer.apple.com/documentation/virtualization?language=objc)
=======
[![Build](https://github.com/Code-Hex/vz/actions/workflows/compile.yml/badge.svg)](https://github.com/Code-Hex/vz/actions/workflows/compile.yml) [![Go Reference](https://pkg.go.dev/badge/github.com/Code-Hex/vz/v3.svg)](https://pkg.go.dev/github.com/Code-Hex/vz/v3)
vz provides the power of the Apple Virtualization.framework in Go. Put here is block quote of overreview which is written what is Virtualization.framework from the document.
> The Virtualization framework provides high-level APIs for creating and managing virtual machines (VM) on Apple silicon and Intel-based Mac computers. Use this framework to boot and run macOS or Linux-based operating systems in custom environments that you define. The framework supports the [Virtual I/O Device (VIRTIO)](https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html) specification, which defines standard interfaces for many device types, including network, socket, serial port, storage, entropy, and memory-balloon devices.
## Usage
Please see the [example](https://github.com/Code-Hex/vz/tree/main/example) directory.
## Requirements
- Higher or equal to macOS Big Sur (11.0.0).
- Latest version of vz supports last two Go major [releases](https://go.dev/doc/devel/release) and might work with older versions.
## Installation
Initialize your project by creating a folder and then running `go mod init github.com/your/repo` ([learn more](https://go.dev/blog/using-go-modules)) inside the folder. Then install vz with the go get command:
```
$ go get github.com/Code-Hex/vz/v3
```
Deprecated older versions (v1, v2).
## Feature Overview
- ✅ Virtualize Linux on a Mac **(x86_64, arm64)**
- GUI Support
- Boot Extensible Firmware Interface (EFI) ROM
- Clipboard sharing through the SPICE agent
- ✅ Virtualize macOS on Apple Silicon Macs **(arm64)**
- Fetches the latest restore image supported by this host from the network
- Start in recovery mode
- ✅ Running Intel Binaries in Linux VMs with Rosetta **(arm64)**
- ✅ [Shared Directories](https://github.com/Code-Hex/vz/wiki/Shared-Directories)
- ✅ [Virtio Sockets](https://github.com/Code-Hex/vz/wiki/Sockets)
- ✅ Less dependent (only under golang.org/x/*)
## Important
For binaries used in this package, you need to create an entitlements file like the one below and apply the following command.
<details>
<summary>vz.entitlements</summary>
```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.virtualization</key>
<true/>
</dict>
</plist>
```
</details>
```sh
$ codesign --entitlements vz.entitlements -s - <YOUR BINARY PATH>
```
> A process must have the com.apple.security.virtualization entitlement to use the Virtualization APIs.
If you want to use [`VZBridgedNetworkDeviceAttachment`](https://developer.apple.com/documentation/virtualization/vzbridgednetworkdeviceattachment?language=objc), you need to add also `com.apple.vm.networking` entitlement.
## Known compile-time warnings
If you compile using an older Xcode SDK, you will get the following warnings.
This example warns that macOS 12.3 API and macOS 13 API are not available in the binary build. Running this binary on a modern OS (macOS 12.3 or macOS 13) means that these APIs are not available. This means these APIs are not available even if you are running this binary on a modern OS (macOS 12.3 or macOS 13).
```
$ go build .
# github.com/Code-Hex/vz/v3
In file included from _cgo_export.c:4:
In file included from socket.go:6:
In file included from ./virtualization_11.h:9:
./virtualization_helper.h:25:9: warning: macOS 12.3 API has been disabled [-W#pragma-messages]
./virtualization_helper.h:32:9: warning: macOS 13 API has been disabled [-W#pragma-messages]
```
If you want to build a binary that can use the API on all operating systems, make sure the Xcode SDK is up-to-date.
You can check the version of the Xcode SDK available for each macOS on this site.
https://xcodereleases.com/
## Version compatibility check
The package provides a mechanism for checking the availability of the respective API through error handling:
```go
bootLoader, err := vz.NewEFIBootLoader()
if errors.Is(err, vz.ErrUnsupportedOSVersion) || errors.Is(err, ErrBuildTargetOSVersion) {
return fallbackBootLoader()
}
if err != nil {
return nil, err
}
return bootLoader, nil
```
There are two items to check.
1. API is compatible with the version of macOS
2. The binary was built with the API enabled
## Knowledge for the Apple Virtualization.framework
There is a lot of knowledge required to use this Apple Virtualization.framework, but the information is too scattered and very difficult to understand. In most cases, this can be found in [the official documentation](https://developer.apple.com/documentation/virtualization?language=objc). However, the Linux kernel knowledge required to use the feature provided by this framework is not documented. Therefore, I have compiled the knowledge I have gathered so far into this wiki.
https://github.com/Code-Hex/vz/wiki
Anyone is free to edit this wiki. It would help someone if you could add information not listed here. Let's make a good wiki together!
## Testing
If you want to contribute some code, you will need to add tests.
[PUI PUI Linux](https://github.com/Code-Hex/puipui-linux) is used to test this library. This Linux is designed to provide only the minimum functionality required for the Apple Virtualization.framework (Virtio), so the kernel file size is very small.
The test code uses the `Makefile` in the project root.
```
$ # Download PUI PUI Linux, Only required the first time.
$ make download_kernel
$ make test
```
## LICENSE
MIT License

View File

@@ -0,0 +1,141 @@
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"
*/
import "C"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// AudioDeviceConfiguration interface for an audio device configuration.
type AudioDeviceConfiguration interface {
objc.NSObject
audioDeviceConfiguration()
}
type baseAudioDeviceConfiguration struct{}
func (*baseAudioDeviceConfiguration) audioDeviceConfiguration() {}
// VirtioSoundDeviceConfiguration is a struct that defines a Virtio sound device configuration.
//
// Use a VirtioSoundDeviceConfiguration to configure an audio device for your VM. After creating
// this struct, assign appropriate values via the SetStreams method which defines the behaviors of
// the underlying audio streams for this audio device.
//
// After creating and configuring a VirtioSoundDeviceConfiguration struct, assign it to the
// SetAudioDevicesVirtualMachineConfiguration method of your VMs configuration.
type VirtioSoundDeviceConfiguration struct {
*pointer
*baseAudioDeviceConfiguration
}
var _ AudioDeviceConfiguration = (*VirtioSoundDeviceConfiguration)(nil)
// NewVirtioSoundDeviceConfiguration creates a new sound device configuration.
//
// This is only supported on macOS 12 and newer, error will be returned
// on older versions.
func NewVirtioSoundDeviceConfiguration() (*VirtioSoundDeviceConfiguration, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
config := &VirtioSoundDeviceConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioSoundDeviceConfiguration(),
),
}
objc.SetFinalizer(config, func(self *VirtioSoundDeviceConfiguration) {
objc.Release(self)
})
return config, nil
}
// SetStreams sets the list of audio streams exposed by this device.
func (v *VirtioSoundDeviceConfiguration) SetStreams(streams ...VirtioSoundDeviceStreamConfiguration) {
ptrs := make([]objc.NSObject, len(streams))
for i, val := range streams {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setStreamsVZVirtioSoundDeviceConfiguration(
objc.Ptr(v), objc.Ptr(array),
)
}
// VirtioSoundDeviceStreamConfiguration interface for Virtio Sound Device Stream Configuration.
type VirtioSoundDeviceStreamConfiguration interface {
objc.NSObject
virtioSoundDeviceStreamConfiguration()
}
type baseVirtioSoundDeviceStreamConfiguration struct{}
func (*baseVirtioSoundDeviceStreamConfiguration) virtioSoundDeviceStreamConfiguration() {}
// VirtioSoundDeviceHostInputStreamConfiguration is a PCM stream of input audio data,
// such as from a microphone via host.
type VirtioSoundDeviceHostInputStreamConfiguration struct {
*pointer
*baseVirtioSoundDeviceStreamConfiguration
}
var _ VirtioSoundDeviceStreamConfiguration = (*VirtioSoundDeviceHostInputStreamConfiguration)(nil)
// NewVirtioSoundDeviceHostInputStreamConfiguration creates a new PCM stream configuration of input audio data from host.
//
// This is only supported on macOS 12 and newer, error will be returned
// on older versions.
func NewVirtioSoundDeviceHostInputStreamConfiguration() (*VirtioSoundDeviceHostInputStreamConfiguration, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
config := &VirtioSoundDeviceHostInputStreamConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioSoundDeviceHostInputStreamConfiguration(),
),
}
objc.SetFinalizer(config, func(self *VirtioSoundDeviceHostInputStreamConfiguration) {
objc.Release(self)
})
return config, nil
}
// VirtioSoundDeviceHostOutputStreamConfiguration is a struct that
// defines a Virtio host sound device output stream configuration.
//
// A PCM stream of output audio data, such as to a speaker from host.
type VirtioSoundDeviceHostOutputStreamConfiguration struct {
*pointer
*baseVirtioSoundDeviceStreamConfiguration
}
var _ VirtioSoundDeviceStreamConfiguration = (*VirtioSoundDeviceHostOutputStreamConfiguration)(nil)
// NewVirtioSoundDeviceHostOutputStreamConfiguration creates a new sounds device output stream configuration.
//
// This is only supported on macOS 12 and newer, error will be returned
// on older versions.
func NewVirtioSoundDeviceHostOutputStreamConfiguration() (*VirtioSoundDeviceHostOutputStreamConfiguration, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
config := &VirtioSoundDeviceHostOutputStreamConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioSoundDeviceHostOutputStreamConfiguration(),
),
}
objc.SetFinalizer(config, func(self *VirtioSoundDeviceHostOutputStreamConfiguration) {
objc.Release(self)
})
return config, nil
}

View File

@@ -0,0 +1,226 @@
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_13.h"
*/
import "C"
import (
"fmt"
"os"
"github.com/Code-Hex/vz/v3/internal/objc"
)
// BootLoader is the interface of boot loader definitions.
type BootLoader interface {
objc.NSObject
bootLoader()
}
type baseBootLoader struct{}
func (*baseBootLoader) bootLoader() {}
var _ BootLoader = (*LinuxBootLoader)(nil)
// LinuxBootLoader Boot loader configuration for a Linux kernel.
// see: https://developer.apple.com/documentation/virtualization/vzlinuxbootloader?language=objc
type LinuxBootLoader struct {
vmlinuzPath string
initrdPath string
cmdLine string
*pointer
*baseBootLoader
}
func (b *LinuxBootLoader) String() string {
return fmt.Sprintf(
"vmlinuz: %q, initrd: %q, command-line: %q",
b.vmlinuzPath,
b.initrdPath,
b.cmdLine,
)
}
// LinuxBootLoaderOption is an option for LinuxBootLoader.
type LinuxBootLoaderOption func(b *LinuxBootLoader) error
// WithCommandLine sets the command-line parameters.
// see: https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
func WithCommandLine(cmdLine string) LinuxBootLoaderOption {
return func(b *LinuxBootLoader) error {
b.cmdLine = cmdLine
cs := charWithGoString(cmdLine)
defer cs.Free()
C.setCommandLineVZLinuxBootLoader(objc.Ptr(b), cs.CString())
return nil
}
}
// WithInitrd sets the optional initial RAM disk.
func WithInitrd(initrdPath string) LinuxBootLoaderOption {
return func(b *LinuxBootLoader) error {
if _, err := os.Stat(initrdPath); err != nil {
return fmt.Errorf("invalid initial RAM disk path: %w", err)
}
b.initrdPath = initrdPath
cs := charWithGoString(initrdPath)
defer cs.Free()
C.setInitialRamdiskURLVZLinuxBootLoader(objc.Ptr(b), cs.CString())
return nil
}
}
// NewLinuxBootLoader creates a LinuxBootLoader with the Linux kernel passed as Path.
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewLinuxBootLoader(vmlinuz string, opts ...LinuxBootLoaderOption) (*LinuxBootLoader, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
if _, err := os.Stat(vmlinuz); err != nil {
return nil, fmt.Errorf("invalid linux kernel path: %w", err)
}
vmlinuzPath := charWithGoString(vmlinuz)
defer vmlinuzPath.Free()
bootLoader := &LinuxBootLoader{
vmlinuzPath: vmlinuz,
pointer: objc.NewPointer(
C.newVZLinuxBootLoader(vmlinuzPath.CString()),
),
}
objc.SetFinalizer(bootLoader, func(self *LinuxBootLoader) {
objc.Release(self)
})
for _, opt := range opts {
if err := opt(bootLoader); err != nil {
return nil, err
}
}
return bootLoader, nil
}
var _ BootLoader = (*LinuxBootLoader)(nil)
// EFIBootLoader Boot loader configuration for booting guest operating systems expecting an EFI ROM.
// see: https://developer.apple.com/documentation/virtualization/vzefibootloader?language=objc
type EFIBootLoader struct {
*pointer
*baseBootLoader
variableStore *EFIVariableStore
}
// NewEFIBootLoaderOption is an option type to initialize a new EFIBootLoader.
type NewEFIBootLoaderOption func(b *EFIBootLoader)
// WithEFIVariableStore sets the optional EFI variable store.
func WithEFIVariableStore(variableStore *EFIVariableStore) NewEFIBootLoaderOption {
return func(e *EFIBootLoader) {
C.setVariableStoreVZEFIBootLoader(objc.Ptr(e), objc.Ptr(variableStore))
e.variableStore = variableStore
}
}
// NewEFIBootLoader creates a new EFI boot loader.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewEFIBootLoader(opts ...NewEFIBootLoaderOption) (*EFIBootLoader, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
bootLoader := &EFIBootLoader{
pointer: objc.NewPointer(
C.newVZEFIBootLoader(),
),
}
for _, optFunc := range opts {
optFunc(bootLoader)
}
objc.SetFinalizer(bootLoader, func(self *EFIBootLoader) {
objc.Release(self)
})
return bootLoader, nil
}
// VariableStore returns EFI variable store.
func (e *EFIBootLoader) VariableStore() *EFIVariableStore {
return e.variableStore
}
// EFIVariableStore is EFI variable store.
// The EFI variable store contains NVRAM variables exposed by the EFI ROM.
//
// see: https://developer.apple.com/documentation/virtualization/vzefivariablestore?language=objc
type EFIVariableStore struct {
*pointer
path string
}
// NewEFIVariableStoreOption is an option type to initialize a new EFIVariableStore.
type NewEFIVariableStoreOption func(*EFIVariableStore) error
// WithCreatingEFIVariableStore is an option to initialized VZEFIVariableStore to a path on a file system.
// If the variable store already exists in path, it is overwritten.
func WithCreatingEFIVariableStore() NewEFIVariableStoreOption {
return func(es *EFIVariableStore) error {
cpath := charWithGoString(es.path)
defer cpath.Free()
nserrPtr := newNSErrorAsNil()
es.pointer = objc.NewPointer(
C.newCreatingVZEFIVariableStoreAtPath(
cpath.CString(),
&nserrPtr,
),
)
if err := newNSError(nserrPtr); err != nil {
return err
}
return nil
}
}
// NewEFIVariableStore Initialize the variable store. If no options are specified,
// it initialises from the paths that exist.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewEFIVariableStore(path string, opts ...NewEFIVariableStoreOption) (*EFIVariableStore, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
variableStore := &EFIVariableStore{path: path}
for _, optFunc := range opts {
if err := optFunc(variableStore); err != nil {
return nil, err
}
}
if objc.Ptr(variableStore) == nil {
if _, err := os.Stat(path); err != nil {
return nil, err
}
cpath := charWithGoString(path)
defer cpath.Free()
variableStore.pointer = objc.NewPointer(
C.newVZEFIVariableStorePath(cpath.CString()),
)
}
objc.SetFinalizer(variableStore, func(self *EFIVariableStore) {
objc.Release(self)
})
return variableStore, nil
}
// Path returns the path of the variable store on the local file system.
func (e *EFIVariableStore) Path() string { return e.path }

View File

@@ -0,0 +1,43 @@
//go:build darwin && arm64
// +build darwin,arm64
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_12_arm64.h"
*/
import "C"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// MacOSBootLoader is a boot loader configuration for booting macOS on Apple Silicon.
type MacOSBootLoader struct {
*pointer
*baseBootLoader
}
var _ BootLoader = (*MacOSBootLoader)(nil)
// NewMacOSBootLoader creates a new MacOSBootLoader struct.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacOSBootLoader() (*MacOSBootLoader, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
bootLoader := &MacOSBootLoader{
pointer: objc.NewPointer(
C.newVZMacOSBootLoader(),
),
}
objc.SetFinalizer(bootLoader, func(self *MacOSBootLoader) {
objc.Release(self)
})
return bootLoader, nil
}

View File

@@ -0,0 +1,139 @@
package vz
/*
#cgo darwin CFLAGS: -mmacosx-version-min=11 -x objective-c
#cgo darwin LDFLAGS: -lobjc -framework Foundation
#import <Foundation/Foundation.h>
const char *getNSErrorLocalizedDescription(void *err)
{
NSString *ld = (NSString *)[(NSError *)err localizedDescription];
return [ld UTF8String];
}
const char *getNSErrorDomain(void *err)
{
NSString *domain = (NSString *)[(NSError *)err domain];
return [domain UTF8String];
}
const char *getNSErrorUserInfo(void *err)
{
NSDictionary<NSErrorUserInfoKey, id> *ui = [(NSError *)err userInfo];
NSString *uis = [NSString stringWithFormat:@"%@", ui];
return [uis UTF8String];
}
NSInteger getNSErrorCode(void *err)
{
return (NSInteger)[(NSError *)err code];
}
typedef struct NSErrorFlat {
const char *domain;
const char *localizedDescription;
const char *userinfo;
int code;
} NSErrorFlat;
NSErrorFlat convertNSError2Flat(void *err)
{
NSErrorFlat ret;
ret.domain = getNSErrorDomain(err);
ret.localizedDescription = getNSErrorLocalizedDescription(err);
ret.userinfo = getNSErrorUserInfo(err);
ret.code = (int)getNSErrorCode(err);
return ret;
}
void *newNSError()
{
NSError *err = nil;
return err;
}
bool hasError(void *err)
{
return (NSError *)err != nil;
}
*/
import "C"
import (
"fmt"
"unsafe"
"github.com/Code-Hex/vz/v3/internal/objc"
)
// pointer is a type alias which is able to use as embedded type and
// makes as unexported it.
type pointer = objc.Pointer
// NSError indicates NSError.
type NSError struct {
Domain string
Code int
LocalizedDescription string
UserInfo string
}
// newNSErrorAsNil makes nil NSError in objective-c world.
func newNSErrorAsNil() unsafe.Pointer {
return unsafe.Pointer(C.newNSError())
}
// hasNSError checks passed pointer is NSError or not.
func hasNSError(nserrPtr unsafe.Pointer) bool {
return (bool)(C.hasError(nserrPtr))
}
func (n *NSError) Error() string {
if n == nil {
return "<nil>"
}
return fmt.Sprintf(
"Error Domain=%s Code=%d Description=%q UserInfo=%s",
n.Domain,
n.Code,
n.LocalizedDescription,
n.UserInfo,
)
}
func newNSError(p unsafe.Pointer) *NSError {
if !hasNSError(p) {
return nil
}
nsError := C.convertNSError2Flat(p)
return &NSError{
Domain: (*char)(nsError.domain).String(),
Code: int((nsError.code)),
LocalizedDescription: (*char)(nsError.localizedDescription).String(),
UserInfo: (*char)(nsError.userinfo).String(), // NOTE(codehex): maybe we can convert to map[string]interface{}
}
}
// CharWithGoString makes *Char which is *C.Char wrapper from Go string.
func charWithGoString(s string) *char {
return (*char)(unsafe.Pointer(C.CString(s)))
}
// Char is a wrapper of C.char
type char C.char
// CString converts *C.char from *Char
func (c *char) CString() *C.char {
return (*C.char)(c)
}
// String converts Go string from *Char
func (c *char) String() string {
return C.GoString((*C.char)(c))
}
// Free frees allocated *C.char in Go code
func (c *char) Free() {
C.free(unsafe.Pointer(c))
}

View File

@@ -0,0 +1,66 @@
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_13.h"
*/
import "C"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// SpiceAgentPortAttachment is an attachment point that enables
// the Spice clipboard sharing capability.
//
// see: https://developer.apple.com/documentation/virtualization/vzspiceagentportattachment?language=objc
type SpiceAgentPortAttachment struct {
*pointer
*baseSerialPortAttachment
enabledSharesClipboard bool
}
var _ SerialPortAttachment = (*SpiceAgentPortAttachment)(nil)
// NewSpiceAgentPortAttachment creates a new Spice agent port attachment.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewSpiceAgentPortAttachment() (*SpiceAgentPortAttachment, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
spiceAgent := &SpiceAgentPortAttachment{
pointer: objc.NewPointer(
C.newVZSpiceAgentPortAttachment(),
),
enabledSharesClipboard: true,
}
objc.SetFinalizer(spiceAgent, func(self *SpiceAgentPortAttachment) {
objc.Release(self)
})
return spiceAgent, nil
}
// SetSharesClipboard sets enable the Spice agent clipboard sharing capability.
func (s *SpiceAgentPortAttachment) SetSharesClipboard(enable bool) {
C.setSharesClipboardVZSpiceAgentPortAttachment(
objc.Ptr(s),
C.bool(enable),
)
s.enabledSharesClipboard = enable
}
// SharesClipboard returns enable the Spice agent clipboard sharing capability.
func (s *SpiceAgentPortAttachment) SharesClipboard() bool { return s.enabledSharesClipboard }
// SpiceAgentPortAttachmentName returns the Spice agent port name.
func SpiceAgentPortAttachmentName() (string, error) {
if err := macOSAvailable(13); err != nil {
return "", err
}
cstring := (*char)(C.getSpiceAgentPortName())
return cstring.String(), nil
}

View File

@@ -0,0 +1,299 @@
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_13.h"
*/
import "C"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// VirtualMachineConfiguration defines the configuration of a VirtualMachine.
//
// The following properties must be configured before creating a virtual machine:
// - bootLoader
//
// The configuration of devices is often done in two parts:
// - Device configuration
// - Device attachment
//
// The device configuration defines the characteristics of the emulated hardware device.
// For example, for a network device, the device configuration defines the type of network adapter present
// in the virtual machine and its MAC address.
//
// The device attachment defines the host machine's resources that are exposed by the virtual device.
// For example, for a network device, the device attachment can be virtual network interface with a NAT
// to the real network.
//
// Creating a virtual machine using the Virtualization framework requires the app to have the "com.apple.security.virtualization" entitlement.
// A VirtualMachineConfiguration is considered invalid if the application does not have the entitlement.
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtualmachineconfiguration?language=objc
type VirtualMachineConfiguration struct {
cpuCount uint
memorySize uint64
*pointer
}
// NewVirtualMachineConfiguration creates a new configuration.
//
// - bootLoader parameter is used when the virtual machine starts.
// - cpu parameter is The number of CPUs must be a value between
// VZVirtualMachineConfiguration.minimumAllowedCPUCount and VZVirtualMachineConfiguration.maximumAllowedCPUCount.
// - memorySize parameter represents memory size in bytes.
// The memory size must be a multiple of a 1 megabyte (1024 * 1024 bytes) between
// VZVirtualMachineConfiguration.minimumAllowedMemorySize and VZVirtualMachineConfiguration.maximumAllowedMemorySize.
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewVirtualMachineConfiguration(bootLoader BootLoader, cpu uint, memorySize uint64) (*VirtualMachineConfiguration, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
config := &VirtualMachineConfiguration{
cpuCount: cpu,
memorySize: memorySize,
pointer: objc.NewPointer(
C.newVZVirtualMachineConfiguration(
objc.Ptr(bootLoader),
C.uint(cpu),
C.ulonglong(memorySize),
),
),
}
objc.SetFinalizer(config, func(self *VirtualMachineConfiguration) {
objc.Release(self)
})
return config, nil
}
// Validate the configuration.
//
// Return true if the configuration is valid.
// If error is not nil, assigned with the validation error if the validation failed.
func (v *VirtualMachineConfiguration) Validate() (bool, error) {
nserrPtr := newNSErrorAsNil()
ret := C.validateVZVirtualMachineConfiguration(objc.Ptr(v), &nserrPtr)
err := newNSError(nserrPtr)
if err != nil {
return false, err
}
return (bool)(ret), nil
}
// SetEntropyDevicesVirtualMachineConfiguration sets list of entropy devices. Empty by default.
func (v *VirtualMachineConfiguration) SetEntropyDevicesVirtualMachineConfiguration(cs []*VirtioEntropyDeviceConfiguration) {
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setEntropyDevicesVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// SetMemoryBalloonDevicesVirtualMachineConfiguration sets list of memory balloon devices. Empty by default.
func (v *VirtualMachineConfiguration) SetMemoryBalloonDevicesVirtualMachineConfiguration(cs []MemoryBalloonDeviceConfiguration) {
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setMemoryBalloonDevicesVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// SetNetworkDevicesVirtualMachineConfiguration sets list of network adapters. Empty by default.
func (v *VirtualMachineConfiguration) SetNetworkDevicesVirtualMachineConfiguration(cs []*VirtioNetworkDeviceConfiguration) {
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setNetworkDevicesVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// NetworkDevices return the list of network device configuration set in this virtual machine configuration.
// Return an empty array if no network device configuration is set.
func (v *VirtualMachineConfiguration) NetworkDevices() []*VirtioNetworkDeviceConfiguration {
nsArray := objc.NewNSArray(
C.networkDevicesVZVirtualMachineConfiguration(objc.Ptr(v)),
)
ptrs := nsArray.ToPointerSlice()
networkDevices := make([]*VirtioNetworkDeviceConfiguration, len(ptrs))
for i, ptr := range ptrs {
networkDevices[i] = newVirtioNetworkDeviceConfiguration(ptr)
}
return networkDevices
}
// SetSerialPortsVirtualMachineConfiguration sets list of serial ports. Empty by default.
func (v *VirtualMachineConfiguration) SetSerialPortsVirtualMachineConfiguration(cs []*VirtioConsoleDeviceSerialPortConfiguration) {
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setSerialPortsVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// SetSocketDevicesVirtualMachineConfiguration sets list of socket devices. Empty by default.
func (v *VirtualMachineConfiguration) SetSocketDevicesVirtualMachineConfiguration(cs []SocketDeviceConfiguration) {
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setSocketDevicesVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// SocketDevices return the list of socket device configuration configured in this virtual machine configuration.
// Return an empty array if no socket device configuration is set.
func (v *VirtualMachineConfiguration) SocketDevices() []SocketDeviceConfiguration {
nsArray := objc.NewNSArray(
C.socketDevicesVZVirtualMachineConfiguration(objc.Ptr(v)),
)
ptrs := nsArray.ToPointerSlice()
socketDevices := make([]SocketDeviceConfiguration, len(ptrs))
for i, ptr := range ptrs {
socketDevices[i] = newVirtioSocketDeviceConfiguration(ptr)
}
return socketDevices
}
// SetStorageDevicesVirtualMachineConfiguration sets list of disk devices. Empty by default.
func (v *VirtualMachineConfiguration) SetStorageDevicesVirtualMachineConfiguration(cs []StorageDeviceConfiguration) {
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setStorageDevicesVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// SetDirectorySharingDevicesVirtualMachineConfiguration sets list of directory sharing devices. Empty by default.
//
// This is only supported on macOS 12 and newer. Older versions do nothing.
func (v *VirtualMachineConfiguration) SetDirectorySharingDevicesVirtualMachineConfiguration(cs []DirectorySharingDeviceConfiguration) {
if err := macOSAvailable(12); err != nil {
return
}
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setDirectorySharingDevicesVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// SetPlatformVirtualMachineConfiguration sets the hardware platform to use. Defaults to GenericPlatformConfiguration.
//
// This is only supported on macOS 12 and newer. Older versions do nothing.
func (v *VirtualMachineConfiguration) SetPlatformVirtualMachineConfiguration(c PlatformConfiguration) {
if err := macOSAvailable(12); err != nil {
return
}
C.setPlatformVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(c))
}
// SetGraphicsDevicesVirtualMachineConfiguration sets list of graphics devices. Empty by default.
//
// This is only supported on macOS 12 and newer. Older versions do nothing.
func (v *VirtualMachineConfiguration) SetGraphicsDevicesVirtualMachineConfiguration(cs []GraphicsDeviceConfiguration) {
if err := macOSAvailable(12); err != nil {
return
}
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setGraphicsDevicesVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// SetPointingDevicesVirtualMachineConfiguration sets list of pointing devices. Empty by default.
//
// This is only supported on macOS 12 and newer. Older versions do nothing.
func (v *VirtualMachineConfiguration) SetPointingDevicesVirtualMachineConfiguration(cs []PointingDeviceConfiguration) {
if err := macOSAvailable(12); err != nil {
return
}
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setPointingDevicesVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// SetKeyboardsVirtualMachineConfiguration sets list of keyboards. Empty by default.
//
// This is only supported on macOS 12 and newer. Older versions do nothing.
func (v *VirtualMachineConfiguration) SetKeyboardsVirtualMachineConfiguration(cs []KeyboardConfiguration) {
if err := macOSAvailable(12); err != nil {
return
}
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setKeyboardsVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// SetAudioDevicesVirtualMachineConfiguration sets list of audio devices. Empty by default.
//
// This is only supported on macOS 12 and newer. Older versions do nothing.
func (v *VirtualMachineConfiguration) SetAudioDevicesVirtualMachineConfiguration(cs []AudioDeviceConfiguration) {
if err := macOSAvailable(12); err != nil {
return
}
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setAudioDevicesVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// SetConsoleDevicesVirtualMachineConfiguration sets list of console devices. Empty by default.
//
// This is only supported on macOS 13 and newer. Older versions do nothing.
func (v *VirtualMachineConfiguration) SetConsoleDevicesVirtualMachineConfiguration(cs []ConsoleDeviceConfiguration) {
if err := macOSAvailable(13); err != nil {
return
}
ptrs := make([]objc.NSObject, len(cs))
for i, val := range cs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setConsoleDevicesVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// VirtualMachineConfigurationMinimumAllowedMemorySize returns minimum
// amount of memory required by virtual machines.
func VirtualMachineConfigurationMinimumAllowedMemorySize() uint64 {
return uint64(C.minimumAllowedMemorySizeVZVirtualMachineConfiguration())
}
// VirtualMachineConfigurationMaximumAllowedMemorySize returns maximum
// amount of memory allowed for a virtual machine.
func VirtualMachineConfigurationMaximumAllowedMemorySize() uint64 {
return uint64(C.maximumAllowedMemorySizeVZVirtualMachineConfiguration())
}
// VirtualMachineConfigurationMinimumAllowedCPUCount returns minimum
// number of CPUs for a virtual machine.
func VirtualMachineConfigurationMinimumAllowedCPUCount() uint {
return uint(C.minimumAllowedCPUCountVZVirtualMachineConfiguration())
}
// VirtualMachineConfigurationMaximumAllowedCPUCount returns maximum
// number of CPUs for a virtual machine.
func VirtualMachineConfigurationMaximumAllowedCPUCount() uint {
return uint(C.maximumAllowedCPUCountVZVirtualMachineConfiguration())
}

View File

@@ -0,0 +1,173 @@
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_13.h"
*/
import "C"
import (
"unsafe"
"github.com/Code-Hex/vz/v3/internal/objc"
)
// ConsoleDeviceConfiguration interface for an console device configuration.
type ConsoleDeviceConfiguration interface {
objc.NSObject
consoleDeviceConfiguration()
}
type baseConsoleDeviceConfiguration struct{}
func (*baseConsoleDeviceConfiguration) consoleDeviceConfiguration() {}
// VirtioConsoleDeviceConfiguration is Virtio Console Device.
type VirtioConsoleDeviceConfiguration struct {
*pointer
portsPtr unsafe.Pointer
*baseConsoleDeviceConfiguration
consolePorts map[int]*VirtioConsolePortConfiguration
}
var _ ConsoleDeviceConfiguration = (*VirtioConsoleDeviceConfiguration)(nil)
// NewVirtioConsoleDeviceConfiguration creates a new VirtioConsoleDeviceConfiguration.
func NewVirtioConsoleDeviceConfiguration() (*VirtioConsoleDeviceConfiguration, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
config := &VirtioConsoleDeviceConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioConsoleDeviceConfiguration(),
),
consolePorts: make(map[int]*VirtioConsolePortConfiguration),
}
config.portsPtr = C.portsVZVirtioConsoleDeviceConfiguration(objc.Ptr(config))
objc.SetFinalizer(config, func(self *VirtioConsoleDeviceConfiguration) {
objc.Release(self)
})
return config, nil
}
// MaximumPortCount returns the maximum number of ports allocated by this device.
// The default is the number of ports attached to this device.
func (v *VirtioConsoleDeviceConfiguration) MaximumPortCount() uint32 {
return uint32(C.maximumPortCountVZVirtioConsolePortConfigurationArray(v.portsPtr))
}
func (v *VirtioConsoleDeviceConfiguration) SetVirtioConsolePortConfiguration(idx int, portConfig *VirtioConsolePortConfiguration) {
C.setObjectAtIndexedSubscriptVZVirtioConsolePortConfigurationArray(
v.portsPtr,
objc.Ptr(portConfig),
C.int(idx),
)
// to mark as currently reachable.
// This ensures that the object is not freed, and its finalizer is not run
v.consolePorts[idx] = portConfig
}
type ConsolePortConfiguration interface {
objc.NSObject
consolePortConfiguration()
}
type baseConsolePortConfiguration struct{}
func (*baseConsolePortConfiguration) consolePortConfiguration() {}
// VirtioConsolePortConfiguration is Virtio Console Port
//
// A console port is a two-way communication channel between a host VZSerialPortAttachment and
// a virtual machine console port. One or more console ports are attached to a Virtio console device.
type VirtioConsolePortConfiguration struct {
*pointer
*baseConsolePortConfiguration
isConsole bool
name string
attachment SerialPortAttachment
}
var _ ConsolePortConfiguration = (*VirtioConsolePortConfiguration)(nil)
// NewVirtioConsolePortConfigurationOption is an option type to initialize a new VirtioConsolePortConfiguration
type NewVirtioConsolePortConfigurationOption func(*VirtioConsolePortConfiguration)
// WithVirtioConsolePortConfigurationName sets the console port's name.
// The default behavior is to not use a name unless set.
func WithVirtioConsolePortConfigurationName(name string) NewVirtioConsolePortConfigurationOption {
return func(vcpc *VirtioConsolePortConfiguration) {
consolePortName := charWithGoString(name)
defer consolePortName.Free()
C.setNameVZVirtioConsolePortConfiguration(
objc.Ptr(vcpc),
consolePortName.CString(),
)
vcpc.name = name
}
}
// WithVirtioConsolePortConfigurationIsConsole sets the console port may be marked
// for use as the system console. The default is false.
func WithVirtioConsolePortConfigurationIsConsole(isConsole bool) NewVirtioConsolePortConfigurationOption {
return func(vcpc *VirtioConsolePortConfiguration) {
C.setIsConsoleVZVirtioConsolePortConfiguration(
objc.Ptr(vcpc),
C.bool(isConsole),
)
vcpc.isConsole = isConsole
}
}
// WithVirtioConsolePortConfigurationAttachment sets the console port attachment.
// The default is nil.
func WithVirtioConsolePortConfigurationAttachment(attachment SerialPortAttachment) NewVirtioConsolePortConfigurationOption {
return func(vcpc *VirtioConsolePortConfiguration) {
C.setAttachmentVZVirtioConsolePortConfiguration(
objc.Ptr(vcpc),
objc.Ptr(attachment),
)
vcpc.attachment = attachment
}
}
// NewVirtioConsolePortConfiguration creates a new VirtioConsolePortConfiguration.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewVirtioConsolePortConfiguration(opts ...NewVirtioConsolePortConfigurationOption) (*VirtioConsolePortConfiguration, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
vcpc := &VirtioConsolePortConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioConsolePortConfiguration(),
),
}
for _, optFunc := range opts {
optFunc(vcpc)
}
objc.SetFinalizer(vcpc, func(self *VirtioConsolePortConfiguration) {
objc.Release(self)
})
return vcpc, nil
}
// Name returns the console port's name.
func (v *VirtioConsolePortConfiguration) Name() string { return v.name }
// IsConsole returns the console port may be marked for use as the system console.
func (v *VirtioConsolePortConfiguration) IsConsole() bool { return v.isConsole }
// Attachment returns the console port attachment.
func (v *VirtioConsolePortConfiguration) Attachment() SerialPortAttachment {
return v.attachment
}

View File

@@ -0,0 +1,65 @@
//go:build darwin && debug
// +build darwin,debug
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_debug.h"
*/
import "C"
import (
"runtime"
"github.com/Code-Hex/vz/v3/internal/objc"
)
// DebugStubConfiguration is an interface to debug configuration.
type DebugStubConfiguration interface {
objc.NSObject
debugStubConfiguration()
}
type baseDebugStubConfiguration struct{}
func (*baseDebugStubConfiguration) debugStubConfiguration() {}
// GDBDebugStubConfiguration is a configuration for gdb debugging.
type GDBDebugStubConfiguration struct {
*pointer
*baseDebugStubConfiguration
}
var _ DebugStubConfiguration = (*GDBDebugStubConfiguration)(nil)
// NewGDBDebugStubConfiguration creates a new GDB debug confiuration.
//
// This API is not officially published and is subject to change without notice.
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewGDBDebugStubConfiguration(port uint32) (*GDBDebugStubConfiguration, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
config := &GDBDebugStubConfiguration{
pointer: objc.NewPointer(
C.newVZGDBDebugStubConfiguration(C.uint32_t(port)),
),
}
objc.SetFinalizer(config, func(self *GDBDebugStubConfiguration) {
objc.Release(self)
})
return config, nil
}
// SetDebugStubVirtualMachineConfiguration sets debug stub configuration. Empty by default.
//
// This API is not officially published and is subject to change without notice.
func (v *VirtualMachineConfiguration) SetDebugStubVirtualMachineConfiguration(dc DebugStubConfiguration) {
C.setDebugStubVZVirtualMachineConfiguration(objc.Ptr(v), objc.Ptr(dc))
}

View File

@@ -0,0 +1,23 @@
package vz
import (
"os"
)
// CreateDiskImage is creating disk image with specified filename and filesize.
// For example, if you want to create disk with 64GiB, you can set "64 * 1024 * 1024 * 1024" to size.
//
// Note that if you have specified a pathname which already exists, this function
// returns os.ErrExist error. So you can handle it with os.IsExist function.
func CreateDiskImage(pathname string, size int64) error {
f, err := os.OpenFile(pathname, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
if err != nil {
return err
}
defer f.Close()
if err := f.Truncate(size); err != nil {
return err
}
return nil
}

View File

@@ -1,12 +1,14 @@
package vz
/*
#cgo darwin CFLAGS: -x objective-c -fno-objc-arc
#cgo darwin CFLAGS: -mmacosx-version-min=11 -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization.h"
# include "virtualization_11.h"
*/
import "C"
import "runtime"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// VirtioEntropyDeviceConfiguration is used to expose a source of entropy for the guest operating systems random-number generator.
// When you create this object and add it to your virtual machines configuration, the virtual machine configures a Virtio-compliant
@@ -14,18 +16,25 @@ import "runtime"
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtioentropydeviceconfiguration?language=objc
type VirtioEntropyDeviceConfiguration struct {
pointer
*pointer
}
// NewVirtioEntropyDeviceConfiguration creates a new Virtio Entropy Device confiuration.
func NewVirtioEntropyDeviceConfiguration() *VirtioEntropyDeviceConfiguration {
config := &VirtioEntropyDeviceConfiguration{
pointer: pointer{
ptr: C.newVZVirtioEntropyDeviceConfiguration(),
},
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewVirtioEntropyDeviceConfiguration() (*VirtioEntropyDeviceConfiguration, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
runtime.SetFinalizer(config, func(self *VirtioEntropyDeviceConfiguration) {
self.Release()
config := &VirtioEntropyDeviceConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioEntropyDeviceConfiguration(),
),
}
objc.SetFinalizer(config, func(self *VirtioEntropyDeviceConfiguration) {
objc.Release(self)
})
return config
return config, nil
}

View File

@@ -0,0 +1,51 @@
// Code generated by "stringer -type=ErrorCode"; DO NOT EDIT.
package vz
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[ErrorInternal-1]
_ = x[ErrorInvalidVirtualMachineConfiguration-2]
_ = x[ErrorInvalidVirtualMachineState-3]
_ = x[ErrorInvalidVirtualMachineStateTransition-4]
_ = x[ErrorInvalidDiskImage-5]
_ = x[ErrorVirtualMachineLimitExceeded-6]
_ = x[ErrorNetworkError-7]
_ = x[ErrorOutOfDiskSpace-8]
_ = x[ErrorOperationCancelled-9]
_ = x[ErrorNotSupported-10]
_ = x[ErrorRestoreImageCatalogLoadFailed-10001]
_ = x[ErrorInvalidRestoreImageCatalog-10002]
_ = x[ErrorNoSupportedRestoreImagesInCatalog-10003]
_ = x[ErrorRestoreImageLoadFailed-10004]
_ = x[ErrorInvalidRestoreImage-10005]
_ = x[ErrorInstallationRequiresUpdate-10006]
_ = x[ErrorInstallationFailed-10007]
}
const (
_ErrorCode_name_0 = "ErrorInternalErrorInvalidVirtualMachineConfigurationErrorInvalidVirtualMachineStateErrorInvalidVirtualMachineStateTransitionErrorInvalidDiskImageErrorVirtualMachineLimitExceededErrorNetworkErrorErrorOutOfDiskSpaceErrorOperationCancelledErrorNotSupported"
_ErrorCode_name_1 = "ErrorRestoreImageCatalogLoadFailedErrorInvalidRestoreImageCatalogErrorNoSupportedRestoreImagesInCatalogErrorRestoreImageLoadFailedErrorInvalidRestoreImageErrorInstallationRequiresUpdateErrorInstallationFailed"
)
var (
_ErrorCode_index_0 = [...]uint8{0, 13, 52, 83, 124, 145, 177, 194, 213, 236, 253}
_ErrorCode_index_1 = [...]uint8{0, 34, 65, 103, 130, 154, 185, 208}
)
func (i ErrorCode) String() string {
switch {
case 1 <= i && i <= 10:
i -= 1
return _ErrorCode_name_0[_ErrorCode_index_0[i]:_ErrorCode_index_0[i+1]]
case 10001 <= i && i <= 10007:
i -= 10001
return _ErrorCode_name_1[_ErrorCode_index_1[i]:_ErrorCode_index_1[i+1]]
default:
return "ErrorCode(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View File

@@ -0,0 +1,98 @@
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_13.h"
*/
import "C"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// GraphicsDeviceConfiguration is an interface for a graphics device configuration.
type GraphicsDeviceConfiguration interface {
objc.NSObject
graphicsDeviceConfiguration()
}
type baseGraphicsDeviceConfiguration struct{}
func (*baseGraphicsDeviceConfiguration) graphicsDeviceConfiguration() {}
// VirtioGraphicsDeviceConfiguration is configuration that represents the configuration
// of a Virtio graphics device for a Linux VM.
//
// This device configuration creates a graphics device using paravirtualization.
// The emulated device follows the Virtio GPU Device specification.
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtiographicsdeviceconfiguration?language=objc
type VirtioGraphicsDeviceConfiguration struct {
*pointer
*baseGraphicsDeviceConfiguration
}
var _ GraphicsDeviceConfiguration = (*VirtioGraphicsDeviceConfiguration)(nil)
// NewVirtioGraphicsDeviceConfiguration creates a new Virtio graphics device.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewVirtioGraphicsDeviceConfiguration() (*VirtioGraphicsDeviceConfiguration, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
graphicsConfiguration := &VirtioGraphicsDeviceConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioGraphicsDeviceConfiguration(),
),
}
objc.SetFinalizer(graphicsConfiguration, func(self *VirtioGraphicsDeviceConfiguration) {
objc.Release(self)
})
return graphicsConfiguration, nil
}
// SetScanouts sets the displays associated with this graphics device.
//
// Maximum of one scanout is supported.
func (v *VirtioGraphicsDeviceConfiguration) SetScanouts(scanoutConfigs ...*VirtioGraphicsScanoutConfiguration) {
ptrs := make([]objc.NSObject, len(scanoutConfigs))
for i, val := range scanoutConfigs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setScanoutsVZVirtioGraphicsDeviceConfiguration(objc.Ptr(v), objc.Ptr(array))
}
// VirtioGraphicsScanoutConfiguration is the configuration for a Virtio graphics device
// that configures the dimensions of the graphics device for a Linux VM.
// see: https://developer.apple.com/documentation/virtualization/vzvirtiographicsscanoutconfiguration?language=objc
type VirtioGraphicsScanoutConfiguration struct {
*pointer
}
// NewVirtioGraphicsScanoutConfiguration creates a Virtio graphics device with the specified dimensions.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewVirtioGraphicsScanoutConfiguration(widthInPixels int64, heightInPixels int64) (*VirtioGraphicsScanoutConfiguration, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
graphicsScanoutConfiguration := &VirtioGraphicsScanoutConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioGraphicsScanoutConfiguration(
C.NSInteger(widthInPixels),
C.NSInteger(heightInPixels),
),
),
}
objc.SetFinalizer(graphicsScanoutConfiguration, func(self *VirtioGraphicsScanoutConfiguration) {
objc.Release(self)
})
return graphicsScanoutConfiguration, nil
}

View File

@@ -0,0 +1,84 @@
//go:build darwin && arm64
// +build darwin,arm64
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_12_arm64.h"
*/
import "C"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// MacGraphicsDeviceConfiguration is a configuration for a display attached to a Mac graphics device.
type MacGraphicsDeviceConfiguration struct {
*pointer
*baseGraphicsDeviceConfiguration
}
var _ GraphicsDeviceConfiguration = (*MacGraphicsDeviceConfiguration)(nil)
// NewMacGraphicsDeviceConfiguration creates a new MacGraphicsDeviceConfiguration.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacGraphicsDeviceConfiguration() (*MacGraphicsDeviceConfiguration, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
graphicsConfiguration := &MacGraphicsDeviceConfiguration{
pointer: objc.NewPointer(
C.newVZMacGraphicsDeviceConfiguration(),
),
}
objc.SetFinalizer(graphicsConfiguration, func(self *MacGraphicsDeviceConfiguration) {
objc.Release(self)
})
return graphicsConfiguration, nil
}
// SetDisplays sets the displays associated with this graphics device.
func (m *MacGraphicsDeviceConfiguration) SetDisplays(displayConfigs ...*MacGraphicsDisplayConfiguration) {
ptrs := make([]objc.NSObject, len(displayConfigs))
for i, val := range displayConfigs {
ptrs[i] = val
}
array := objc.ConvertToNSMutableArray(ptrs)
C.setDisplaysVZMacGraphicsDeviceConfiguration(objc.Ptr(m), objc.Ptr(array))
}
// MacGraphicsDisplayConfiguration is the configuration for a Mac graphics device.
type MacGraphicsDisplayConfiguration struct {
*pointer
}
// NewMacGraphicsDisplayConfiguration creates a new MacGraphicsDisplayConfiguration.
//
// Creates a display configuration with the specified pixel dimensions and pixel density.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacGraphicsDisplayConfiguration(widthInPixels int64, heightInPixels int64, pixelsPerInch int64) (*MacGraphicsDisplayConfiguration, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
graphicsDisplayConfiguration := &MacGraphicsDisplayConfiguration{
pointer: objc.NewPointer(
C.newVZMacGraphicsDisplayConfiguration(
C.NSInteger(widthInPixels),
C.NSInteger(heightInPixels),
C.NSInteger(pixelsPerInch),
),
),
}
objc.SetFinalizer(graphicsDisplayConfiguration, func(self *MacGraphicsDisplayConfiguration) {
objc.Release(self)
})
return graphicsDisplayConfiguration, nil
}

View File

@@ -0,0 +1,10 @@
//go:build !go1.18
// +build !go1.18
package objc
import "runtime"
func SetFinalizer(obj interface{}, finalizer interface{}) {
runtime.SetFinalizer(obj, finalizer)
}

View File

@@ -0,0 +1,10 @@
//go:build go1.18
// +build go1.18
package objc
import "runtime"
func SetFinalizer[T any](obj T, finalizer func(T)) {
runtime.SetFinalizer(obj, finalizer)
}

View File

@@ -0,0 +1,160 @@
package objc
/*
#cgo darwin CFLAGS: -mmacosx-version-min=11 -x objective-c
#cgo darwin LDFLAGS: -lobjc -framework Foundation
#import <Foundation/Foundation.h>
void *makeNSMutableArray(unsigned long cap)
{
return [[NSMutableArray alloc] initWithCapacity:(NSUInteger)cap];
}
void addNSMutableArrayVal(void *ary, void *val)
{
[(NSMutableArray *)ary addObject:(NSObject *)val];
}
void *makeNSMutableDictionary()
{
return [[NSMutableDictionary alloc] init];
}
void insertNSMutableDictionary(void *dict, char *key, void *val)
{
NSString *nskey = [NSString stringWithUTF8String: key];
[(NSMutableDictionary *)dict setValue:(NSObject *)val forKey:nskey];
}
void releaseNSObject(void* o)
{
@autoreleasepool {
[(NSObject*)o release];
}
}
static inline void releaseDispatch(void *queue)
{
dispatch_release((dispatch_queue_t)queue);
}
int getNSArrayCount(void *ptr)
{
return (int)[(NSArray*)ptr count];
}
void* getNSArrayItem(void *ptr, int i)
{
NSArray *arr = (NSArray *)ptr;
return [arr objectAtIndex:i];
}
const char *getUUID()
{
NSString *uuid = [[NSUUID UUID] UUIDString];
return [uuid UTF8String];
}
*/
import "C"
import (
"runtime"
"unsafe"
)
// ReleaseDispatch releases allocated dispatch_queue_t
func ReleaseDispatch(p unsafe.Pointer) {
C.releaseDispatch(p)
}
// Pointer indicates any pointers which are allocated in objective-c world.
type Pointer struct {
_ptr unsafe.Pointer
}
// NewPointer creates a new Pointer for objc
func NewPointer(p unsafe.Pointer) *Pointer {
return &Pointer{_ptr: p}
}
// release releases allocated resources in objective-c world.
func (p *Pointer) release() {
C.releaseNSObject(p._ptr)
runtime.KeepAlive(p)
}
// Ptr returns raw pointer.
func (o *Pointer) ptr() unsafe.Pointer {
if o == nil {
return nil
}
return o._ptr
}
// NSObject indicates NSObject
type NSObject interface {
ptr() unsafe.Pointer
release()
}
// Release releases allocated resources in objective-c world.
func Release(o NSObject) {
o.release()
}
// Ptr returns unsafe.Pointer of the NSObject
func Ptr(o NSObject) unsafe.Pointer {
return o.ptr()
}
// NSArray indicates NSArray
type NSArray struct {
*Pointer
}
// NewNSArray creates a new NSArray from pointer.
func NewNSArray(p unsafe.Pointer) *NSArray {
return &NSArray{NewPointer(p)}
}
// ToPointerSlice method returns slice of the obj-c object as unsafe.Pointer.
func (n *NSArray) ToPointerSlice() []unsafe.Pointer {
count := int(C.getNSArrayCount(n.ptr()))
ret := make([]unsafe.Pointer, count)
for i := 0; i < count; i++ {
ret[i] = C.getNSArrayItem(n.ptr(), C.int(i))
}
return ret
}
// ConvertToNSMutableArray converts to NSMutableArray from NSObject slice in Go world.
func ConvertToNSMutableArray(s []NSObject) *Pointer {
ln := len(s)
ary := C.makeNSMutableArray(C.ulong(ln))
for _, v := range s {
C.addNSMutableArrayVal(ary, v.ptr())
}
p := NewPointer(ary)
runtime.SetFinalizer(p, func(self *Pointer) {
self.release()
})
return p
}
// ConvertToNSMutableDictionary converts to NSMutableDictionary from map[string]NSObject in Go world.
func ConvertToNSMutableDictionary(d map[string]NSObject) *Pointer {
dict := C.makeNSMutableDictionary()
for key, value := range d {
cs := (*C.char)(C.CString(key))
C.insertNSMutableDictionary(dict, cs, value.ptr())
C.free(unsafe.Pointer(cs))
}
p := NewPointer(dict)
runtime.SetFinalizer(p, func(self *Pointer) {
self.release()
})
return p
}
func GetUUID() *C.char {
return C.getUUID()
}

View File

@@ -0,0 +1,62 @@
package progress
import (
"io"
"sync"
"sync/atomic"
)
// Reader is an io.Reader for checking progress.
type Reader struct {
once sync.Once
reader io.Reader
total int64
current int64
finish chan struct{}
err error
}
// NewReader create a new io.Reader for checking progress.
func NewReader(rd io.Reader, total, current int64) *Reader {
return &Reader{
reader: rd,
total: total,
current: current,
finish: make(chan struct{}),
}
}
var _ io.Reader = (*Reader)(nil)
// Finish finishes the progress check operation.
func (r *Reader) Finish(err error) {
r.once.Do(func() {
r.err = err
close(r.finish)
})
}
// Err returns err.
func (r *Reader) Err() error { return r.err }
// Finish sends notification when finished any progress.
func (r *Reader) Finished() <-chan struct{} { return r.finish }
// FractionCompleted returns the fraction of the overall work completed by this progress struct,
// including work done by any children it may have.
func (r *Reader) FractionCompleted() float64 {
return float64(r.Current()) / float64(r.total)
}
func (r *Reader) Current() int64 {
return atomic.LoadInt64(&r.current)
}
// Read reads data using underlying io.Reader.
// The number of bytes read is added to the current progress status.
func (r *Reader) Read(p []byte) (n int, err error) {
n, err = r.reader.Read(p)
atomic.AddInt64(&r.current, int64(n))
return
}

View File

@@ -0,0 +1,49 @@
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"
*/
import "C"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// KeyboardConfiguration interface for a keyboard configuration.
type KeyboardConfiguration interface {
objc.NSObject
keyboardConfiguration()
}
type baseKeyboardConfiguration struct{}
func (*baseKeyboardConfiguration) keyboardConfiguration() {}
// USBKeyboardConfiguration is a device that defines the configuration for a USB keyboard.
type USBKeyboardConfiguration struct {
*pointer
*baseKeyboardConfiguration
}
var _ KeyboardConfiguration = (*USBKeyboardConfiguration)(nil)
// NewUSBKeyboardConfiguration creates a new USB keyboard configuration.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewUSBKeyboardConfiguration() (*USBKeyboardConfiguration, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
config := &USBKeyboardConfiguration{
pointer: objc.NewPointer(C.newVZUSBKeyboardConfiguration()),
}
objc.SetFinalizer(config, func(self *USBKeyboardConfiguration) {
objc.Release(self)
})
return config, nil
}

View File

@@ -0,0 +1,28 @@
//go:build darwin && arm64
// +build darwin,arm64
// Code generated by "stringer -type=LinuxRosettaAvailability -output=linuxrosettaavailability_string_arm64.go"; DO NOT EDIT.
package vz
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[LinuxRosettaAvailabilityNotSupported-0]
_ = x[LinuxRosettaAvailabilityNotInstalled-1]
_ = x[LinuxRosettaAvailabilityInstalled-2]
}
const _LinuxRosettaAvailability_name = "LinuxRosettaAvailabilityNotSupportedLinuxRosettaAvailabilityNotInstalledLinuxRosettaAvailabilityInstalled"
var _LinuxRosettaAvailability_index = [...]uint8{0, 36, 72, 105}
func (i LinuxRosettaAvailability) String() string {
if i < 0 || i >= LinuxRosettaAvailability(len(_LinuxRosettaAvailability_index)-1) {
return "LinuxRosettaAvailability(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _LinuxRosettaAvailability_name[_LinuxRosettaAvailability_index[i]:_LinuxRosettaAvailability_index[i+1]]
}

View File

@@ -1,16 +1,18 @@
package vz
/*
#cgo darwin CFLAGS: -x objective-c -fno-objc-arc
#cgo darwin CFLAGS: -mmacosx-version-min=11 -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization.h"
# include "virtualization_11.h"
*/
import "C"
import "runtime"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// MemoryBalloonDeviceConfiguration for a memory balloon device configuration.
type MemoryBalloonDeviceConfiguration interface {
NSObject
objc.NSObject
memoryBalloonDeviceConfiguration()
}
@@ -25,20 +27,27 @@ var _ MemoryBalloonDeviceConfiguration = (*VirtioTraditionalMemoryBalloonDeviceC
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtiotraditionalmemoryballoondeviceconfiguration?language=objc
type VirtioTraditionalMemoryBalloonDeviceConfiguration struct {
pointer
*pointer
*baseMemoryBalloonDeviceConfiguration
}
// NewVirtioTraditionalMemoryBalloonDeviceConfiguration creates a new VirtioTraditionalMemoryBalloonDeviceConfiguration.
func NewVirtioTraditionalMemoryBalloonDeviceConfiguration() *VirtioTraditionalMemoryBalloonDeviceConfiguration {
config := &VirtioTraditionalMemoryBalloonDeviceConfiguration{
pointer: pointer{
ptr: C.newVZVirtioTraditionalMemoryBalloonDeviceConfiguration(),
},
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewVirtioTraditionalMemoryBalloonDeviceConfiguration() (*VirtioTraditionalMemoryBalloonDeviceConfiguration, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
runtime.SetFinalizer(config, func(self *VirtioTraditionalMemoryBalloonDeviceConfiguration) {
self.Release()
config := &VirtioTraditionalMemoryBalloonDeviceConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioTraditionalMemoryBalloonDeviceConfiguration(),
),
}
objc.SetFinalizer(config, func(self *VirtioTraditionalMemoryBalloonDeviceConfiguration) {
objc.Release(self)
})
return config
return config, nil
}

View File

@@ -1,15 +1,20 @@
package vz
/*
#cgo darwin CFLAGS: -x objective-c -fno-objc-arc
#cgo darwin CFLAGS: -mmacosx-version-min=11 -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization.h"
# include "virtualization_11.h"
# include "virtualization_13.h"
*/
import "C"
import (
"fmt"
"net"
"os"
"runtime"
"syscall"
"unsafe"
"github.com/Code-Hex/vz/v3/internal/objc"
)
// BridgedNetwork defines a network interface that bridges a physical interface with a virtual machine.
@@ -21,7 +26,7 @@ import (
// TODO(codehex): implement...
// see: https://developer.apple.com/documentation/virtualization/vzbridgednetworkinterface?language=objc
type BridgedNetwork interface {
NSObject
objc.NSObject
// NetworkInterfaces returns the list of network interfaces available for bridging.
NetworkInterfaces() []BridgedNetwork
@@ -40,7 +45,7 @@ type BridgedNetwork interface {
// for accesses to outside networks.
// see: https://developer.apple.com/documentation/virtualization/vznatnetworkdeviceattachment?language=objc
type NATNetworkDeviceAttachment struct {
pointer
*pointer
*baseNetworkDeviceAttachment
}
@@ -48,16 +53,21 @@ type NATNetworkDeviceAttachment struct {
var _ NetworkDeviceAttachment = (*NATNetworkDeviceAttachment)(nil)
// NewNATNetworkDeviceAttachment creates a new NATNetworkDeviceAttachment.
func NewNATNetworkDeviceAttachment() *NATNetworkDeviceAttachment {
attachment := &NATNetworkDeviceAttachment{
pointer: pointer{
ptr: C.newVZNATNetworkDeviceAttachment(),
},
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewNATNetworkDeviceAttachment() (*NATNetworkDeviceAttachment, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
runtime.SetFinalizer(attachment, func(self *NATNetworkDeviceAttachment) {
self.Release()
attachment := &NATNetworkDeviceAttachment{
pointer: objc.NewPointer(C.newVZNATNetworkDeviceAttachment()),
}
objc.SetFinalizer(attachment, func(self *NATNetworkDeviceAttachment) {
objc.Release(self)
})
return attachment
return attachment, nil
}
// BridgedNetworkDeviceAttachment represents a physical interface on the host computer.
@@ -71,7 +81,7 @@ func NewNATNetworkDeviceAttachment() *NATNetworkDeviceAttachment {
//
// see: https://developer.apple.com/documentation/virtualization/vzbridgednetworkdeviceattachment?language=objc
type BridgedNetworkDeviceAttachment struct {
pointer
*pointer
*baseNetworkDeviceAttachment
}
@@ -79,18 +89,25 @@ type BridgedNetworkDeviceAttachment struct {
var _ NetworkDeviceAttachment = (*BridgedNetworkDeviceAttachment)(nil)
// NewBridgedNetworkDeviceAttachment creates a new BridgedNetworkDeviceAttachment with networkInterface.
func NewBridgedNetworkDeviceAttachment(networkInterface BridgedNetwork) *BridgedNetworkDeviceAttachment {
attachment := &BridgedNetworkDeviceAttachment{
pointer: pointer{
ptr: C.newVZBridgedNetworkDeviceAttachment(
networkInterface.Ptr(),
),
},
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewBridgedNetworkDeviceAttachment(networkInterface BridgedNetwork) (*BridgedNetworkDeviceAttachment, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
runtime.SetFinalizer(attachment, func(self *BridgedNetworkDeviceAttachment) {
self.Release()
attachment := &BridgedNetworkDeviceAttachment{
pointer: objc.NewPointer(
C.newVZBridgedNetworkDeviceAttachment(
objc.Ptr(networkInterface),
),
),
}
objc.SetFinalizer(attachment, func(self *BridgedNetworkDeviceAttachment) {
objc.Release(self)
})
return attachment
return attachment, nil
}
// FileHandleNetworkDeviceAttachment sending raw network packets over a file handle.
@@ -99,9 +116,11 @@ func NewBridgedNetworkDeviceAttachment(networkInterface BridgedNetwork) *Bridged
// The data transmitted through this attachment is at the level of the data link layer.
// see: https://developer.apple.com/documentation/virtualization/vzfilehandlenetworkdeviceattachment?language=objc
type FileHandleNetworkDeviceAttachment struct {
pointer
*pointer
*baseNetworkDeviceAttachment
mtu int
}
var _ NetworkDeviceAttachment = (*FileHandleNetworkDeviceAttachment)(nil)
@@ -109,24 +128,90 @@ var _ NetworkDeviceAttachment = (*FileHandleNetworkDeviceAttachment)(nil)
// NewFileHandleNetworkDeviceAttachment initialize the attachment with a file handle.
//
// file parameter is holding a connected datagram socket.
func NewFileHandleNetworkDeviceAttachment(file *os.File) *FileHandleNetworkDeviceAttachment {
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewFileHandleNetworkDeviceAttachment(file *os.File) (*FileHandleNetworkDeviceAttachment, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
err := validateDatagramSocket(int(file.Fd()))
if err != nil {
return nil, err
}
attachment := &FileHandleNetworkDeviceAttachment{
pointer: pointer{
ptr: C.newVZFileHandleNetworkDeviceAttachment(
pointer: objc.NewPointer(
C.newVZFileHandleNetworkDeviceAttachment(
C.int(file.Fd()),
),
},
),
mtu: 1500, // The default MTU is 1500.
}
runtime.SetFinalizer(attachment, func(self *FileHandleNetworkDeviceAttachment) {
self.Release()
objc.SetFinalizer(attachment, func(self *FileHandleNetworkDeviceAttachment) {
objc.Release(self)
})
return attachment
return attachment, nil
}
func validateDatagramSocket(fd int) error {
sotype, err := syscall.GetsockoptInt(
fd,
syscall.SOL_SOCKET,
syscall.SO_TYPE,
)
if err != nil {
return os.NewSyscallError("getsockopt", err)
}
if sotype == syscall.SOCK_DGRAM && isAvailableDatagram(fd) {
return nil
}
return fmt.Errorf("The fileHandle must be a datagram socket")
}
func isAvailableDatagram(fd int) bool {
lsa, _ := syscall.Getsockname(fd)
switch lsa.(type) {
case *syscall.SockaddrInet4, *syscall.SockaddrInet6, *syscall.SockaddrUnix:
return true
}
return false
}
// SetMaximumTransmissionUnit sets the maximum transmission unit (MTU) associated with this attachment.
//
// The maximum MTU allowed is 65535, and the minimum MTU allowed is 1500. An invalid MTU value will result in an invalid
// virtual machine configuration.
//
// The client side of the associated datagram socket must be properly configured with the appropriate values
// for SO_SNDBUF, and SO_RCVBUF. Set these using the setsockopt(_:_:_:_:_:) system call. The system expects
// the value of SO_RCVBUF to be at least double the value of SO_SNDBUF, and for optimal performance, the
// recommended value of SO_RCVBUF is four times the value of SO_SNDBUF.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func (f *FileHandleNetworkDeviceAttachment) SetMaximumTransmissionUnit(mtu int) error {
if err := macOSAvailable(13); err != nil {
return err
}
C.setMaximumTransmissionUnitVZFileHandleNetworkDeviceAttachment(
objc.Ptr(f),
C.NSInteger(mtu),
)
f.mtu = mtu
return nil
}
// MaximumTransmissionUnit returns the maximum transmission unit (MTU) associated with this attachment.
// The default MTU is 1500.
func (f *FileHandleNetworkDeviceAttachment) MaximumTransmissionUnit() int {
return f.mtu
}
// NetworkDeviceAttachment for a network device attachment.
// see: https://developer.apple.com/documentation/virtualization/vznetworkdeviceattachment?language=objc
type NetworkDeviceAttachment interface {
NSObject
objc.NSObject
networkDeviceAttachment()
}
@@ -144,64 +229,89 @@ func (*baseNetworkDeviceAttachment) networkDeviceAttachment() {}
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtionetworkdeviceconfiguration?language=objc
type VirtioNetworkDeviceConfiguration struct {
pointer
*pointer
}
// NewVirtioNetworkDeviceConfiguration creates a new VirtioNetworkDeviceConfiguration with NetworkDeviceAttachment.
func NewVirtioNetworkDeviceConfiguration(attachment NetworkDeviceAttachment) *VirtioNetworkDeviceConfiguration {
config := &VirtioNetworkDeviceConfiguration{
pointer: pointer{
ptr: C.newVZVirtioNetworkDeviceConfiguration(
attachment.Ptr(),
),
},
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewVirtioNetworkDeviceConfiguration(attachment NetworkDeviceAttachment) (*VirtioNetworkDeviceConfiguration, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
runtime.SetFinalizer(config, func(self *VirtioNetworkDeviceConfiguration) {
self.Release()
config := newVirtioNetworkDeviceConfiguration(
C.newVZVirtioNetworkDeviceConfiguration(
objc.Ptr(attachment),
),
)
objc.SetFinalizer(config, func(self *VirtioNetworkDeviceConfiguration) {
objc.Release(self)
})
return config
return config, nil
}
func (v *VirtioNetworkDeviceConfiguration) SetMacAddress(macAddress *MACAddress) {
C.setNetworkDevicesVZMACAddress(v.Ptr(), macAddress.Ptr())
func newVirtioNetworkDeviceConfiguration(ptr unsafe.Pointer) *VirtioNetworkDeviceConfiguration {
return &VirtioNetworkDeviceConfiguration{
pointer: objc.NewPointer(ptr),
}
}
func (v *VirtioNetworkDeviceConfiguration) SetMACAddress(macAddress *MACAddress) {
C.setNetworkDevicesVZMACAddress(objc.Ptr(v), objc.Ptr(macAddress))
}
// MACAddress represents a media access control address (MAC address), the 48-bit ethernet address.
// see: https://developer.apple.com/documentation/virtualization/vzmacaddress?language=objc
type MACAddress struct {
pointer
*pointer
}
// NewMACAddress creates a new MACAddress with net.HardwareAddr (MAC address).
func NewMACAddress(macAddr net.HardwareAddr) *MACAddress {
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewMACAddress(macAddr net.HardwareAddr) (*MACAddress, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
macAddrChar := charWithGoString(macAddr.String())
defer macAddrChar.Free()
ma := &MACAddress{
pointer: pointer{
ptr: C.newVZMACAddress(macAddrChar.CString()),
},
pointer: objc.NewPointer(
C.newVZMACAddress(macAddrChar.CString()),
),
}
runtime.SetFinalizer(ma, func(self *MACAddress) {
self.Release()
objc.SetFinalizer(ma, func(self *MACAddress) {
objc.Release(self)
})
return ma
return ma, nil
}
// NewRandomLocallyAdministeredMACAddress creates a valid, random, unicast, locally administered address.
func NewRandomLocallyAdministeredMACAddress() *MACAddress {
ma := &MACAddress{
pointer: pointer{
ptr: C.newRandomLocallyAdministeredVZMACAddress(),
},
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewRandomLocallyAdministeredMACAddress() (*MACAddress, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
runtime.SetFinalizer(ma, func(self *MACAddress) {
self.Release()
ma := &MACAddress{
pointer: objc.NewPointer(
C.newRandomLocallyAdministeredVZMACAddress(),
),
}
objc.SetFinalizer(ma, func(self *MACAddress) {
objc.Release(self)
})
return ma
return ma, nil
}
func (m *MACAddress) String() string {
cstring := (*char)(C.getVZMACAddressString(m.Ptr()))
cstring := (*char)(C.getVZMACAddressString(objc.Ptr(m)))
return cstring.String()
}

View File

@@ -0,0 +1,111 @@
package vz
/*
#cgo darwin CFLAGS: -mmacosx-version-min=11 -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation
# include "virtualization_helper.h"
*/
import "C"
import (
"errors"
"fmt"
"strconv"
"strings"
"sync"
"syscall"
"golang.org/x/mod/semver"
)
var (
// ErrUnsupportedOSVersion is returned when calling a method which is only
// available in newer macOS versions.
ErrUnsupportedOSVersion = errors.New("unsupported macOS version")
// ErrBuildTargetOSVersion indicates that the API is available but the
// running program has disabled it.
ErrBuildTargetOSVersion = errors.New("unsupported build target macOS version")
)
func macOSAvailable(version float64) error {
if macOSMajorMinorVersion() < version {
return ErrUnsupportedOSVersion
}
return macOSBuildTargetAvailable(version)
}
var (
majorMinorVersion float64
majorMinorVersionOnce interface{ Do(func()) } = &sync.Once{}
// This can be replaced in the test code to enable mock.
// It will not be changed in production.
sysctl = syscall.Sysctl
)
func fetchMajorMinorVersion() (float64, error) {
osver, err := sysctl("kern.osproductversion")
if err != nil {
return 0, err
}
prefix := "v"
majorMinor := strings.TrimPrefix(semver.MajorMinor(prefix+osver), prefix)
version, err := strconv.ParseFloat(majorMinor, 64)
if err != nil {
return 0, err
}
return version, nil
}
func macOSMajorMinorVersion() float64 {
majorMinorVersionOnce.Do(func() {
version, err := fetchMajorMinorVersion()
if err != nil {
panic(err)
}
majorMinorVersion = version
})
return majorMinorVersion
}
var (
maxAllowedVersion int
maxAllowedVersionOnce interface{ Do(func()) } = &sync.Once{}
getMaxAllowedVersion = func() int {
return int(C.mac_os_x_version_max_allowed())
}
)
func fetchMaxAllowedVersion() int {
maxAllowedVersionOnce.Do(func() {
maxAllowedVersion = getMaxAllowedVersion()
})
return maxAllowedVersion
}
// macOSBuildTargetAvailable checks whether the API available in a given version has been compiled.
func macOSBuildTargetAvailable(version float64) error {
allowedVersion := fetchMaxAllowedVersion()
if allowedVersion == 0 {
return fmt.Errorf("undefined __MAC_OS_X_VERSION_MAX_ALLOWED: %w", ErrBuildTargetOSVersion)
}
// FIXME(codehex): smart way
// This list from AvailabilityVersions.h
var target int
switch version {
case 11:
target = 110000 // __MAC_11_0
case 12:
target = 120000 // __MAC_12_0
case 12.3:
target = 120300 // __MAC_12_3
case 13:
target = 130000 // __MAC_13_0
}
if allowedVersion < target {
return fmt.Errorf("%w for %.1f", ErrBuildTargetOSVersion, version)
}
return nil
}

View File

@@ -0,0 +1,154 @@
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_13.h"
*/
import "C"
import (
"os"
"unsafe"
"github.com/Code-Hex/vz/v3/internal/objc"
)
// PlatformConfiguration is an interface for a platform configuration.
type PlatformConfiguration interface {
objc.NSObject
platformConfiguration()
}
type basePlatformConfiguration struct{}
func (*basePlatformConfiguration) platformConfiguration() {}
// GenericPlatformConfiguration is the platform configuration for a generic Intel or ARM virtual machine.
type GenericPlatformConfiguration struct {
*pointer
*basePlatformConfiguration
machineIdentifier *GenericMachineIdentifier
}
// MachineIdentifier returns the machine identifier.
func (m *GenericPlatformConfiguration) MachineIdentifier() *GenericMachineIdentifier {
return m.machineIdentifier
}
var _ PlatformConfiguration = (*GenericPlatformConfiguration)(nil)
// NewGenericPlatformConfiguration creates a new generic platform configuration.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewGenericPlatformConfiguration(opts ...GenericPlatformConfigurationOption) (*GenericPlatformConfiguration, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
platformConfig := &GenericPlatformConfiguration{
pointer: objc.NewPointer(
C.newVZGenericPlatformConfiguration(),
),
}
for _, optFunc := range opts {
if err := optFunc(platformConfig); err != nil {
return nil, err
}
}
objc.SetFinalizer(platformConfig, func(self *GenericPlatformConfiguration) {
objc.Release(self)
})
return platformConfig, nil
}
// GenericMachineIdentifier is a struct that represents a unique identifier
// for a virtual machine.
type GenericMachineIdentifier struct {
*pointer
dataRepresentation []byte
}
// NewGenericMachineIdentifierWithDataPath initialize a new machine identifier described by the specified pathname.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewGenericMachineIdentifierWithDataPath(pathname string) (*GenericMachineIdentifier, error) {
b, err := os.ReadFile(pathname)
if err != nil {
return nil, err
}
return NewGenericMachineIdentifierWithData(b)
}
// NewGenericMachineIdentifierWithData initialize a new machine identifier described by the specified data representation.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewGenericMachineIdentifierWithData(b []byte) (*GenericMachineIdentifier, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
ptr := C.newVZGenericMachineIdentifierWithBytes(
unsafe.Pointer(&b[0]),
C.int(len(b)),
)
return newGenericMachineIdentifier(ptr), nil
}
// NewGenericMachineIdentifier initialize a new machine identifier is used by guests to uniquely
// identify the virtual hardware.
//
// Two virtual machines running concurrently should not use the same identifier.
//
// If the virtual machine is serialized to disk, the identifier can be preserved in a binary representation through
// DataRepresentation method.
// The identifier can then be recreated with NewGenericMachineIdentifierWithData function from the binary representation.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewGenericMachineIdentifier() (*GenericMachineIdentifier, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
return newGenericMachineIdentifier(C.newVZGenericMachineIdentifier()), nil
}
func newGenericMachineIdentifier(ptr unsafe.Pointer) *GenericMachineIdentifier {
dataRepresentation := C.getVZGenericMachineIdentifierDataRepresentation(ptr)
bytePointer := (*byte)(unsafe.Pointer(dataRepresentation.ptr))
return &GenericMachineIdentifier{
pointer: objc.NewPointer(ptr),
// https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices
dataRepresentation: unsafe.Slice(bytePointer, dataRepresentation.len),
}
}
// DataRepresentation opaque data representation of the machine identifier.
// This can be used to recreate the same machine identifier with NewGenericMachineIdentifierWithData function.
func (g *GenericMachineIdentifier) DataRepresentation() []byte { return g.dataRepresentation }
// GenericPlatformConfigurationOption is an optional function to create its configuration.
type GenericPlatformConfigurationOption func(*GenericPlatformConfiguration) error
// WithGenericMachineIdentifier is an option to create a new GenericPlatformConfiguration.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func WithGenericMachineIdentifier(m *GenericMachineIdentifier) GenericPlatformConfigurationOption {
return func(mpc *GenericPlatformConfiguration) error {
if err := macOSAvailable(13); err != nil {
return err
}
mpc.machineIdentifier = m
C.setMachineIdentifierVZGenericPlatformConfiguration(objc.Ptr(mpc), objc.Ptr(m))
return nil
}
}

View File

@@ -0,0 +1,101 @@
//go:build darwin && arm64
// +build darwin,arm64
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_12_arm64.h"
*/
import "C"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// MacPlatformConfiguration is the platform configuration for booting macOS on Apple silicon.
//
// When creating a VM, the hardwareModel and auxiliaryStorage depend on the restore image that you use to install macOS.
//
// To choose the hardware model, start from MacOSRestoreImage.MostFeaturefulSupportedConfiguration method to get a supported
// configuration, then use its MacOSConfigurationRequirements.HardwareModel method to get the hardware model.
//
// Use the hardware model to set up MacPlatformConfiguration and to initialize a new auxiliary storage with
// `WithCreatingStorage` functional option of the `NewMacAuxiliaryStorage`.
//
// When you save a VM to disk and load it again, you must restore the HardwareModel, MachineIdentifier and
// AuxiliaryStorage methods to their original values.
//
// If you create multiple VMs from the same configuration, each should have a unique auxiliaryStorage and machineIdentifier.
type MacPlatformConfiguration struct {
*pointer
*basePlatformConfiguration
hardwareModel *MacHardwareModel
machineIdentifier *MacMachineIdentifier
auxiliaryStorage *MacAuxiliaryStorage
}
var _ PlatformConfiguration = (*MacPlatformConfiguration)(nil)
// MacPlatformConfigurationOption is an optional function to create its configuration.
type MacPlatformConfigurationOption func(*MacPlatformConfiguration)
// WithMacHardwareModel is an option to create a new MacPlatformConfiguration.
func WithMacHardwareModel(m *MacHardwareModel) MacPlatformConfigurationOption {
return func(mpc *MacPlatformConfiguration) {
mpc.hardwareModel = m
C.setHardwareModelVZMacPlatformConfiguration(objc.Ptr(mpc), objc.Ptr(m))
}
}
// WithMacMachineIdentifier is an option to create a new MacPlatformConfiguration.
func WithMacMachineIdentifier(m *MacMachineIdentifier) MacPlatformConfigurationOption {
return func(mpc *MacPlatformConfiguration) {
mpc.machineIdentifier = m
C.setMachineIdentifierVZMacPlatformConfiguration(objc.Ptr(mpc), objc.Ptr(m))
}
}
// WithMacAuxiliaryStorage is an option to create a new MacPlatformConfiguration.
func WithMacAuxiliaryStorage(m *MacAuxiliaryStorage) MacPlatformConfigurationOption {
return func(mpc *MacPlatformConfiguration) {
mpc.auxiliaryStorage = m
C.setAuxiliaryStorageVZMacPlatformConfiguration(objc.Ptr(mpc), objc.Ptr(m))
}
}
// NewMacPlatformConfiguration creates a new MacPlatformConfiguration. see also it's document.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacPlatformConfiguration(opts ...MacPlatformConfigurationOption) (*MacPlatformConfiguration, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
platformConfig := &MacPlatformConfiguration{
pointer: objc.NewPointer(
C.newVZMacPlatformConfiguration(),
),
}
for _, optFunc := range opts {
optFunc(platformConfig)
}
objc.SetFinalizer(platformConfig, func(self *MacPlatformConfiguration) {
objc.Release(self)
})
return platformConfig, nil
}
// HardwareModel returns the Mac hardware model.
func (m *MacPlatformConfiguration) HardwareModel() *MacHardwareModel { return m.hardwareModel }
// MachineIdentifier returns the Mac machine identifier.
func (m *MacPlatformConfiguration) MachineIdentifier() *MacMachineIdentifier {
return m.machineIdentifier
}
// AuxiliaryStorage returns the Mac auxiliary storage.
func (m *MacPlatformConfiguration) AuxiliaryStorage() *MacAuxiliaryStorage { return m.auxiliaryStorage }

View File

@@ -0,0 +1,52 @@
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"
*/
import "C"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// PointingDeviceConfiguration is an interface for a pointing device configuration.
type PointingDeviceConfiguration interface {
objc.NSObject
pointingDeviceConfiguration()
}
type basePointingDeviceConfiguration struct{}
func (*basePointingDeviceConfiguration) pointingDeviceConfiguration() {}
// USBScreenCoordinatePointingDeviceConfiguration is a struct that defines the configuration
// for a USB pointing device that reports absolute coordinates.
type USBScreenCoordinatePointingDeviceConfiguration struct {
*pointer
*basePointingDeviceConfiguration
}
var _ PointingDeviceConfiguration = (*USBScreenCoordinatePointingDeviceConfiguration)(nil)
// NewUSBScreenCoordinatePointingDeviceConfiguration creates a new USBScreenCoordinatePointingDeviceConfiguration.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewUSBScreenCoordinatePointingDeviceConfiguration() (*USBScreenCoordinatePointingDeviceConfiguration, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
config := &USBScreenCoordinatePointingDeviceConfiguration{
pointer: objc.NewPointer(
C.newVZUSBScreenCoordinatePointingDeviceConfiguration(),
),
}
objc.SetFinalizer(config, func(self *USBScreenCoordinatePointingDeviceConfiguration) {
objc.Release(self)
})
return config, nil
}

View File

@@ -0,0 +1,51 @@
//go:build darwin && arm64
// +build darwin,arm64
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_13_arm64.h"
*/
import "C"
import (
"github.com/Code-Hex/vz/v3/internal/objc"
)
// 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, error will
// be returned on older versions.
func NewMacTrackpadConfiguration() (*MacTrackpadConfiguration, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
config := &MacTrackpadConfiguration{
pointer: objc.NewPointer(
C.newVZMacTrackpadConfiguration(),
),
}
objc.SetFinalizer(config, func(self *MacTrackpadConfiguration) {
objc.Release(self)
})
return config, nil
}

View File

@@ -1,21 +1,22 @@
package vz
/*
#cgo darwin CFLAGS: -x objective-c -fno-objc-arc
#cgo darwin CFLAGS: -mmacosx-version-min=11 -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization
# include "virtualization.h"
# include "virtualization_11.h"
*/
import "C"
import (
"os"
"runtime"
"github.com/Code-Hex/vz/v3/internal/objc"
)
// SerialPortAttachment interface for a serial port attachment.
//
// A serial port attachment defines how the virtual machine's serial port interfaces with the host system.
type SerialPortAttachment interface {
NSObject
objc.NSObject
serialPortAttachment()
}
@@ -31,7 +32,7 @@ var _ SerialPortAttachment = (*FileHandleSerialPortAttachment)(nil)
// Data written to fileHandleForReading goes to the guest. Data sent from the guest appears on fileHandleForWriting.
// see: https://developer.apple.com/documentation/virtualization/vzfilehandleserialportattachment?language=objc
type FileHandleSerialPortAttachment struct {
pointer
*pointer
*baseSerialPortAttachment
}
@@ -40,19 +41,26 @@ type FileHandleSerialPortAttachment struct {
//
// read parameter is an *os.File for reading from the file.
// write parameter is an *os.File for writing to the file.
func NewFileHandleSerialPortAttachment(read, write *os.File) *FileHandleSerialPortAttachment {
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewFileHandleSerialPortAttachment(read, write *os.File) (*FileHandleSerialPortAttachment, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
attachment := &FileHandleSerialPortAttachment{
pointer: pointer{
ptr: C.newVZFileHandleSerialPortAttachment(
pointer: objc.NewPointer(
C.newVZFileHandleSerialPortAttachment(
C.int(read.Fd()),
C.int(write.Fd()),
),
},
),
}
runtime.SetFinalizer(attachment, func(self *FileHandleSerialPortAttachment) {
self.Release()
objc.SetFinalizer(attachment, func(self *FileHandleSerialPortAttachment) {
objc.Release(self)
})
return attachment
return attachment, nil
}
var _ SerialPortAttachment = (*FileSerialPortAttachment)(nil)
@@ -63,7 +71,7 @@ var _ SerialPortAttachment = (*FileSerialPortAttachment)(nil)
// No data is sent to the guest over serial with this attachment.
// see: https://developer.apple.com/documentation/virtualization/vzfileserialportattachment?language=objc
type FileSerialPortAttachment struct {
pointer
*pointer
*baseSerialPortAttachment
}
@@ -71,29 +79,35 @@ type FileSerialPortAttachment struct {
// NewFileSerialPortAttachment initialize the FileSerialPortAttachment from a path of a file.
// If error is not nil, used to report errors if intialization fails.
//
// - path of the file for the attachment on the local file system.
// - shouldAppend True if the file should be opened in append mode, false otherwise.
// When a file is opened in append mode, writing to that file will append to the end of it.
// - path of the file for the attachment on the local file system.
// - shouldAppend True if the file should be opened in append mode, false otherwise.
// When a file is opened in append mode, writing to that file will append to the end of it.
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewFileSerialPortAttachment(path string, shouldAppend bool) (*FileSerialPortAttachment, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
cpath := charWithGoString(path)
defer cpath.Free()
nserr := newNSErrorAsNil()
nserrPtr := nserr.Ptr()
nserrPtr := newNSErrorAsNil()
attachment := &FileSerialPortAttachment{
pointer: pointer{
ptr: C.newVZFileSerialPortAttachment(
pointer: objc.NewPointer(
C.newVZFileSerialPortAttachment(
cpath.CString(),
C.bool(shouldAppend),
&nserrPtr,
),
},
),
}
if err := newNSError(nserrPtr); err != nil {
return nil, err
}
runtime.SetFinalizer(attachment, func(self *FileSerialPortAttachment) {
self.Release()
objc.SetFinalizer(attachment, func(self *FileSerialPortAttachment) {
objc.Release(self)
})
return attachment, nil
}
@@ -104,20 +118,27 @@ func NewFileSerialPortAttachment(path string, shouldAppend bool) (*FileSerialPor
// The device sets up a single port on the Virtio console device.
// see: https://developer.apple.com/documentation/virtualization/vzvirtioconsoledeviceserialportconfiguration?language=objc
type VirtioConsoleDeviceSerialPortConfiguration struct {
pointer
*pointer
}
// NewVirtioConsoleDeviceSerialPortConfiguration creates a new NewVirtioConsoleDeviceSerialPortConfiguration.
func NewVirtioConsoleDeviceSerialPortConfiguration(attachment SerialPortAttachment) *VirtioConsoleDeviceSerialPortConfiguration {
config := &VirtioConsoleDeviceSerialPortConfiguration{
pointer: pointer{
ptr: C.newVZVirtioConsoleDeviceSerialPortConfiguration(
attachment.Ptr(),
),
},
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewVirtioConsoleDeviceSerialPortConfiguration(attachment SerialPortAttachment) (*VirtioConsoleDeviceSerialPortConfiguration, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
runtime.SetFinalizer(config, func(self *VirtioConsoleDeviceSerialPortConfiguration) {
self.Release()
config := &VirtioConsoleDeviceSerialPortConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioConsoleDeviceSerialPortConfiguration(
objc.Ptr(attachment),
),
),
}
objc.SetFinalizer(config, func(self *VirtioConsoleDeviceSerialPortConfiguration) {
objc.Release(self)
})
return config
return config, nil
}

View File

@@ -0,0 +1,184 @@
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_13.h"
*/
import "C"
import (
"os"
"github.com/Code-Hex/vz/v3/internal/objc"
)
// DirectorySharingDeviceConfiguration for a directory sharing device configuration.
type DirectorySharingDeviceConfiguration interface {
objc.NSObject
directorySharingDeviceConfiguration()
}
type baseDirectorySharingDeviceConfiguration struct{}
func (*baseDirectorySharingDeviceConfiguration) directorySharingDeviceConfiguration() {}
var _ DirectorySharingDeviceConfiguration = (*VirtioFileSystemDeviceConfiguration)(nil)
// VirtioFileSystemDeviceConfiguration is a configuration of a Virtio file system device.
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtiofilesystemdeviceconfiguration?language=objc
type VirtioFileSystemDeviceConfiguration struct {
*pointer
*baseDirectorySharingDeviceConfiguration
}
// NewVirtioFileSystemDeviceConfiguration create a new VirtioFileSystemDeviceConfiguration.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewVirtioFileSystemDeviceConfiguration(tag string) (*VirtioFileSystemDeviceConfiguration, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
tagChar := charWithGoString(tag)
defer tagChar.Free()
nserrPtr := newNSErrorAsNil()
fsdConfig := &VirtioFileSystemDeviceConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioFileSystemDeviceConfiguration(tagChar.CString(), &nserrPtr),
),
}
if err := newNSError(nserrPtr); err != nil {
return nil, err
}
objc.SetFinalizer(fsdConfig, func(self *VirtioFileSystemDeviceConfiguration) {
objc.Release(self)
})
return fsdConfig, nil
}
// SetDirectoryShare sets the directory share associated with this configuration.
func (c *VirtioFileSystemDeviceConfiguration) SetDirectoryShare(share DirectoryShare) {
C.setVZVirtioFileSystemDeviceConfigurationShare(objc.Ptr(c), objc.Ptr(share))
}
// SharedDirectory is a shared directory.
type SharedDirectory struct {
*pointer
}
// NewSharedDirectory creates a new shared directory.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewSharedDirectory(dirPath string, readOnly bool) (*SharedDirectory, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
if _, err := os.Stat(dirPath); err != nil {
return nil, err
}
dirPathChar := charWithGoString(dirPath)
defer dirPathChar.Free()
sd := &SharedDirectory{
pointer: objc.NewPointer(
C.newVZSharedDirectory(dirPathChar.CString(), C.bool(readOnly)),
),
}
objc.SetFinalizer(sd, func(self *SharedDirectory) {
objc.Release(self)
})
return sd, nil
}
// DirectoryShare is the base interface for a directory share.
type DirectoryShare interface {
objc.NSObject
directoryShare()
}
type baseDirectoryShare struct{}
func (*baseDirectoryShare) directoryShare() {}
var _ DirectoryShare = (*SingleDirectoryShare)(nil)
// SingleDirectoryShare defines the directory share for a single directory.
type SingleDirectoryShare struct {
*pointer
*baseDirectoryShare
}
// NewSingleDirectoryShare creates a new single directory share.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewSingleDirectoryShare(share *SharedDirectory) (*SingleDirectoryShare, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
config := &SingleDirectoryShare{
pointer: objc.NewPointer(
C.newVZSingleDirectoryShare(objc.Ptr(share)),
),
}
objc.SetFinalizer(config, func(self *SingleDirectoryShare) {
objc.Release(self)
})
return config, nil
}
// MultipleDirectoryShare defines the directory share for multiple directories.
type MultipleDirectoryShare struct {
*pointer
*baseDirectoryShare
}
var _ DirectoryShare = (*MultipleDirectoryShare)(nil)
// NewMultipleDirectoryShare creates a new multiple directories share.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMultipleDirectoryShare(shares map[string]*SharedDirectory) (*MultipleDirectoryShare, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
directories := make(map[string]objc.NSObject, len(shares))
for k, v := range shares {
directories[k] = v
}
dict := objc.ConvertToNSMutableDictionary(directories)
config := &MultipleDirectoryShare{
pointer: objc.NewPointer(
C.newVZMultipleDirectoryShare(objc.Ptr(dict)),
),
}
objc.SetFinalizer(config, func(self *MultipleDirectoryShare) {
objc.Release(self)
})
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, error will be returned on older versions.
func MacOSGuestAutomountTag() (string, error) {
if err := macOSAvailable(13); err != nil {
return "", err
}
cstring := (*char)(C.getMacOSGuestAutomountTag())
return cstring.String(), nil
}

View File

@@ -0,0 +1,109 @@
//go:build darwin && arm64
// +build darwin,arm64
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_13_arm64.h"
*/
import "C"
import (
"runtime/cgo"
"unsafe"
"github.com/Code-Hex/vz/v3/internal/objc"
)
// LinuxRosettaAvailability represents an availability of Rosetta support for Linux binaries.
//
//go:generate go run ./cmd/addtags -tags=darwin,arm64 -file linuxrosettaavailability_string_arm64.go stringer -type=LinuxRosettaAvailability -output=linuxrosettaavailability_string_arm64.go
type LinuxRosettaAvailability int
const (
// LinuxRosettaAvailabilityNotSupported Rosetta support for Linux binaries is not available on the host system.
LinuxRosettaAvailabilityNotSupported LinuxRosettaAvailability = iota
// LinuxRosettaAvailabilityNotInstalled Rosetta support for Linux binaries is not installed on the host system.
LinuxRosettaAvailabilityNotInstalled
// LinuxRosettaAvailabilityInstalled Rosetta support for Linux is installed on the host system.
LinuxRosettaAvailabilityInstalled
)
//export linuxInstallRosettaWithCompletionHandler
func linuxInstallRosettaWithCompletionHandler(cgoHandlerPtr, errPtr unsafe.Pointer) {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
handler := cgoHandler.Value().(func(error))
if err := newNSError(errPtr); err != nil {
handler(err)
} else {
handler(nil)
}
}
// LinuxRosettaDirectoryShare directory share to enable Rosetta support for Linux binaries.
// see: https://developer.apple.com/documentation/virtualization/vzlinuxrosettadirectoryshare?language=objc
type LinuxRosettaDirectoryShare struct {
*pointer
*baseDirectoryShare
}
var _ DirectoryShare = (*LinuxRosettaDirectoryShare)(nil)
// NewLinuxRosettaDirectoryShare creates a new Rosetta directory share if Rosetta support
// for Linux binaries is installed.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewLinuxRosettaDirectoryShare() (*LinuxRosettaDirectoryShare, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
nserrPtr := newNSErrorAsNil()
ds := &LinuxRosettaDirectoryShare{
pointer: objc.NewPointer(
C.newVZLinuxRosettaDirectoryShare(&nserrPtr),
),
}
if err := newNSError(nserrPtr); err != nil {
return nil, err
}
objc.SetFinalizer(ds, func(self *LinuxRosettaDirectoryShare) {
objc.Release(self)
})
return ds, nil
}
// LinuxRosettaDirectoryShareInstallRosetta download and install Rosetta support
// for Linux binaries if necessary.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func LinuxRosettaDirectoryShareInstallRosetta() error {
if err := macOSAvailable(13); err != nil {
return err
}
errCh := make(chan error, 1)
cgoHandler := cgo.NewHandle(func(err error) {
errCh <- err
})
C.linuxInstallRosetta(unsafe.Pointer(&cgoHandler))
return <-errCh
}
// LinuxRosettaDirectoryShareAvailability checks the availability of Rosetta support
// for the directory share.
//
// This is only supported on macOS 13 and newer, LinuxRosettaAvailabilityNotSupported will
// be returned on older versions.
func LinuxRosettaDirectoryShareAvailability() LinuxRosettaAvailability {
if err := macOSAvailable(13); err != nil {
return LinuxRosettaAvailabilityNotSupported
}
return LinuxRosettaAvailability(C.availabilityVZLinuxRosettaDirectoryShare())
}

View File

@@ -0,0 +1,330 @@
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"
*/
import "C"
import (
"fmt"
"net"
"os"
"runtime"
"runtime/cgo"
"sync"
"time"
"unsafe"
"github.com/Code-Hex/vz/v3/internal/objc"
)
// SocketDeviceConfiguration for a socket device configuration.
type SocketDeviceConfiguration interface {
objc.NSObject
socketDeviceConfiguration()
}
type baseSocketDeviceConfiguration struct{}
func (*baseSocketDeviceConfiguration) socketDeviceConfiguration() {}
var _ SocketDeviceConfiguration = (*VirtioSocketDeviceConfiguration)(nil)
// VirtioSocketDeviceConfiguration is a configuration of the Virtio socket device.
//
// This configuration creates a Virtio socket device for the guest which communicates with the host through the Virtio interface.
// Only one Virtio socket device can be used per virtual machine.
// see: https://developer.apple.com/documentation/virtualization/vzvirtiosocketdeviceconfiguration?language=objc
type VirtioSocketDeviceConfiguration struct {
*pointer
*baseSocketDeviceConfiguration
}
// NewVirtioSocketDeviceConfiguration creates a new VirtioSocketDeviceConfiguration.
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewVirtioSocketDeviceConfiguration() (*VirtioSocketDeviceConfiguration, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
config := newVirtioSocketDeviceConfiguration(C.newVZVirtioSocketDeviceConfiguration())
objc.SetFinalizer(config, func(self *VirtioSocketDeviceConfiguration) {
objc.Release(self)
})
return config, nil
}
func newVirtioSocketDeviceConfiguration(ptr unsafe.Pointer) *VirtioSocketDeviceConfiguration {
return &VirtioSocketDeviceConfiguration{
pointer: objc.NewPointer(ptr),
}
}
// VirtioSocketDevice a device that manages port-based connections between the guest system and the host computer.
//
// Dont create a VirtioSocketDevice struct directly. Instead, when you request a socket device in your configuration,
// the virtual machine creates it and you can get it via SocketDevices method.
// see: https://developer.apple.com/documentation/virtualization/vzvirtiosocketdevice?language=objc
type VirtioSocketDevice struct {
dispatchQueue unsafe.Pointer
*pointer
}
func newVirtioSocketDevice(ptr, dispatchQueue unsafe.Pointer) *VirtioSocketDevice {
return &VirtioSocketDevice{
dispatchQueue: dispatchQueue,
pointer: objc.NewPointer(ptr),
}
}
// Listen creates a new VirtioSocketListener which is a struct that listens for port-based connection requests
// from the guest operating system.
//
// Be sure to close the listener by calling `VirtioSocketListener.Close` after used this one.
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func (v *VirtioSocketDevice) Listen(port uint32) (*VirtioSocketListener, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
ch := make(chan connResults, 1) // should I increase more caps?
handler := cgo.NewHandle(func(conn *VirtioSocketConnection, err error) {
ch <- connResults{conn, err}
})
ptr := C.newVZVirtioSocketListener(
unsafe.Pointer(&handler),
)
listener := &VirtioSocketListener{
pointer: objc.NewPointer(ptr),
vsockDevice: v,
port: port,
handler: handler,
acceptch: ch,
}
C.VZVirtioSocketDevice_setSocketListenerForPort(
objc.Ptr(v),
v.dispatchQueue,
objc.Ptr(listener),
C.uint32_t(port),
)
return listener, nil
}
//export connectionHandler
func connectionHandler(connPtr, errPtr, cgoHandlerPtr unsafe.Pointer) {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
handler := cgoHandler.Value().(func(*VirtioSocketConnection, error))
defer cgoHandler.Delete()
// see: startHandler
if err := newNSError(errPtr); err != nil {
handler(nil, err)
} else {
conn, err := newVirtioSocketConnection(connPtr)
handler(conn, err)
}
}
// Connect Initiates a connection to the specified port of the guest operating system.
//
// This method initiates the connection asynchronously, and executes the completion handler when the results are available.
// If the guest operating system doesnt listen for connections to the specifed port, this method does nothing.
//
// For a successful connection, this method sets the sourcePort property of the resulting VZVirtioSocketConnection object to a random port number.
// see: https://developer.apple.com/documentation/virtualization/vzvirtiosocketdevice/3656677-connecttoport?language=objc
func (v *VirtioSocketDevice) Connect(port uint32) (*VirtioSocketConnection, error) {
ch := make(chan connResults, 1)
cgoHandler := cgo.NewHandle(func(conn *VirtioSocketConnection, err error) {
ch <- connResults{conn, err}
close(ch)
})
C.VZVirtioSocketDevice_connectToPort(
objc.Ptr(v),
v.dispatchQueue,
C.uint32_t(port),
unsafe.Pointer(&cgoHandler),
)
result := <-ch
runtime.KeepAlive(v)
return result.conn, result.err
}
type connResults struct {
conn *VirtioSocketConnection
err error
}
// VirtioSocketListener a struct that listens for port-based connection requests from the guest operating system.
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtiosocketlistener?language=objc
type VirtioSocketListener struct {
*pointer
vsockDevice *VirtioSocketDevice
handler cgo.Handle
port uint32
acceptch chan connResults
closeOnce sync.Once
}
var _ net.Listener = (*VirtioSocketListener)(nil)
// Accept implements the Accept method in the Listener interface; it waits for the next call and returns a net.Conn.
func (v *VirtioSocketListener) Accept() (net.Conn, error) {
return v.AcceptVirtioSocketConnection()
}
// AcceptVirtioSocketConnection accepts the next incoming call and returns the new connection.
func (v *VirtioSocketListener) AcceptVirtioSocketConnection() (*VirtioSocketConnection, error) {
result := <-v.acceptch
return result.conn, result.err
}
// Close stops listening on the virtio socket.
func (v *VirtioSocketListener) Close() error {
v.closeOnce.Do(func() {
C.VZVirtioSocketDevice_removeSocketListenerForPort(
objc.Ptr(v.vsockDevice),
v.vsockDevice.dispatchQueue,
C.uint32_t(v.port),
)
v.handler.Delete()
})
return nil
}
// Addr returns the listener's network address, a *VirtioSocketListenerAddr.
func (v *VirtioSocketListener) Addr() net.Addr {
const VMADDR_CID_HOST = 2 // copied from unix pacage
return &VirtioSocketListenerAddr{
CID: VMADDR_CID_HOST,
Port: v.port,
}
}
// VirtioSocketListenerAddr represents a network end point address for the vsock protocol.
type VirtioSocketListenerAddr struct {
CID uint32
Port uint32
}
var _ net.Addr = (*VirtioSocketListenerAddr)(nil)
// Network returns "vsock".
func (a *VirtioSocketListenerAddr) Network() string { return "vsock" }
// String returns string of "<cid>:<port>"
func (a *VirtioSocketListenerAddr) String() string { return fmt.Sprintf("%d:%d", a.CID, a.Port) }
//export shouldAcceptNewConnectionHandler
func shouldAcceptNewConnectionHandler(cgoHandlerPtr, connPtr, devicePtr unsafe.Pointer) C.bool {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
handler := cgoHandler.Value().(func(*VirtioSocketConnection, error))
// see: startHandler
conn, err := newVirtioSocketConnection(connPtr)
go handler(conn, err)
return (C.bool)(true)
}
// VirtioSocketConnection is a port-based connection between the guest operating system and the host computer.
//
// You dont create connection objects directly. When the guest operating system initiates a connection, the virtual machine creates
// the connection object and passes it to the appropriate VirtioSocketListener struct, which forwards the object to its delegate.
//
// This is implemented net.Conn interface. This is generated from duplicated a file descriptor which is returned
// from virtualization.framework. macOS cannot connect directly to the Guest operating system using vsock. The vsock
// connection must always be made via virtualization.framework. The diagram looks like this.
//
// ┌─────────┐ ┌────────────────────────────┐ ┌────────────┐
// │ macOS │<─── unix socket ───>│ virtualization.framework │<─── vsock ───>│ Guest OS │
// └─────────┘ └────────────────────────────┘ └────────────┘
//
// You will notice that this is not vsock in using this library. However, all data this connection goes through to the vsock
// connection to which the Guest OS is connected.
//
// This struct does not have any pointers for objects of the Objective-C. Because the various values
// of the VZVirtioSocketConnection object handled by Objective-C are no longer needed after the conversion
// to the Go struct.
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtiosocketconnection?language=objc
type VirtioSocketConnection struct {
rawConn net.Conn
destinationPort uint32
sourcePort uint32
}
var _ net.Conn = (*VirtioSocketConnection)(nil)
func newVirtioSocketConnection(ptr unsafe.Pointer) (*VirtioSocketConnection, error) {
vzVirtioSocketConnection := C.convertVZVirtioSocketConnection2Flat(ptr)
file := os.NewFile((uintptr)(vzVirtioSocketConnection.fileDescriptor), "")
defer file.Close()
rawConn, err := net.FileConn(file)
if err != nil {
return nil, err
}
conn := &VirtioSocketConnection{
rawConn: rawConn,
destinationPort: (uint32)(vzVirtioSocketConnection.destinationPort),
sourcePort: (uint32)(vzVirtioSocketConnection.sourcePort),
}
return conn, nil
}
// Read reads data from connection of the vsock protocol.
func (v *VirtioSocketConnection) Read(b []byte) (n int, err error) { return v.rawConn.Read(b) }
// Write writes data to the connection of the vsock protocol.
func (v *VirtioSocketConnection) Write(b []byte) (n int, err error) { return v.rawConn.Write(b) }
// Close will be called when caused something error in socket.
func (v *VirtioSocketConnection) Close() error {
return v.rawConn.Close()
}
// LocalAddr returns the local network address.
func (v *VirtioSocketConnection) LocalAddr() net.Addr { return v.rawConn.LocalAddr() }
// RemoteAddr returns the remote network address.
func (v *VirtioSocketConnection) RemoteAddr() net.Addr { return v.rawConn.RemoteAddr() }
// SetDeadline sets the read and write deadlines associated
// with the connection. It is equivalent to calling both
// SetReadDeadline and SetWriteDeadline.
func (v *VirtioSocketConnection) SetDeadline(t time.Time) error { return v.rawConn.SetDeadline(t) }
// SetReadDeadline sets the deadline for future Read calls
// and any currently-blocked Read call.
// A zero value for t means Read will not time out.
func (v *VirtioSocketConnection) SetReadDeadline(t time.Time) error {
return v.rawConn.SetReadDeadline(t)
}
// SetWriteDeadline sets the deadline for future Write calls
// and any currently-blocked Write call.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
// A zero value for t means Write will not time out.
func (v *VirtioSocketConnection) SetWriteDeadline(t time.Time) error {
return v.rawConn.SetWriteDeadline(t)
}
// DestinationPort returns the destination port number of the connection.
func (v *VirtioSocketConnection) DestinationPort() uint32 {
return v.destinationPort
}
// SourcePort returns the source port number of the connection.
func (v *VirtioSocketConnection) SourcePort() uint32 {
return v.sourcePort
}

View File

@@ -0,0 +1,211 @@
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_3.h"
# include "virtualization_13.h"
*/
import "C"
import (
"os"
"github.com/Code-Hex/vz/v3/internal/objc"
)
type baseStorageDeviceAttachment struct{}
func (*baseStorageDeviceAttachment) storageDeviceAttachment() {}
// StorageDeviceAttachment for a storage device attachment.
//
// A storage device attachment defines how a virtual machine storage device interfaces with the host system.
// see: https://developer.apple.com/documentation/virtualization/vzstoragedeviceattachment?language=objc
type StorageDeviceAttachment interface {
objc.NSObject
storageDeviceAttachment()
}
var _ StorageDeviceAttachment = (*DiskImageStorageDeviceAttachment)(nil)
// DiskImageStorageDeviceAttachment is a storage device attachment using a disk image to implement the storage.
//
// This storage device attachment uses a disk image on the host file system as the drive of the storage device.
// Only raw data disk images are supported.
// see: https://developer.apple.com/documentation/virtualization/vzdiskimagestoragedeviceattachment?language=objc
type DiskImageStorageDeviceAttachment struct {
*pointer
*baseStorageDeviceAttachment
}
// NewDiskImageStorageDeviceAttachment 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.
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewDiskImageStorageDeviceAttachment(diskPath string, readOnly bool) (*DiskImageStorageDeviceAttachment, error) {
if err := macOSAvailable(11); 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.newVZDiskImageStorageDeviceAttachment(
diskPathChar.CString(),
C.bool(readOnly),
&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
storageDeviceConfiguration()
}
type baseStorageDeviceConfiguration struct{}
func (*baseStorageDeviceConfiguration) storageDeviceConfiguration() {}
var _ StorageDeviceConfiguration = (*VirtioBlockDeviceConfiguration)(nil)
// VirtioBlockDeviceConfiguration is a configuration of a paravirtualized storage device of type Virtio Block Device.
//
// This device configuration creates a storage device using paravirtualization.
// The emulated device follows the Virtio Block Device specification.
//
// The host implementation of the device is done through an attachment subclassing VZStorageDeviceAttachment
// like VZDiskImageStorageDeviceAttachment.
// see: https://developer.apple.com/documentation/virtualization/vzvirtioblockdeviceconfiguration?language=objc
type VirtioBlockDeviceConfiguration struct {
*pointer
*baseStorageDeviceConfiguration
blockDeviceIdentifier string
}
// NewVirtioBlockDeviceConfiguration initialize a VZVirtioBlockDeviceConfiguration with a device attachment.
//
// - attachment The storage device attachment. This defines how the virtualized device operates on the host side.
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewVirtioBlockDeviceConfiguration(attachment StorageDeviceAttachment) (*VirtioBlockDeviceConfiguration, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
config := &VirtioBlockDeviceConfiguration{
pointer: objc.NewPointer(
C.newVZVirtioBlockDeviceConfiguration(
objc.Ptr(attachment),
),
),
}
objc.SetFinalizer(config, func(self *VirtioBlockDeviceConfiguration) {
objc.Release(self)
})
return config, nil
}
// BlockDeviceIdentifier returns the device identifier is a string identifying the Virtio block device.
// Empty string by default.
//
// The identifier can be retrieved in the guest via a VIRTIO_BLK_T_GET_ID request.
//
// This is only supported on macOS 12.3 and newer, error will be returned on older versions.
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtioblockdeviceconfiguration/3917717-blockdeviceidentifier
func (v *VirtioBlockDeviceConfiguration) BlockDeviceIdentifier() (string, error) {
if err := macOSAvailable(12.3); err != nil {
return "", err
}
return v.blockDeviceIdentifier, nil
}
// SetBlockDeviceIdentifier sets the device identifier is a string identifying the Virtio block device.
//
// The device identifier must be at most 20 bytes in length and ASCII-encodable.
//
// This is only supported on macOS 12.3 and newer, error will be returned on older versions.
//
// see: https://developer.apple.com/documentation/virtualization/vzvirtioblockdeviceconfiguration/3917717-blockdeviceidentifier
func (v *VirtioBlockDeviceConfiguration) SetBlockDeviceIdentifier(identifier string) error {
if err := macOSAvailable(12.3); err != nil {
return err
}
idChar := charWithGoString(identifier)
defer idChar.Free()
nserrPtr := newNSErrorAsNil()
C.setBlockDeviceIdentifierVZVirtioBlockDeviceConfiguration(
objc.Ptr(v),
idChar.CString(),
&nserrPtr,
)
if err := newNSError(nserrPtr); err != nil {
return err
}
v.blockDeviceIdentifier = identifier
return nil
}
// USBMassStorageDeviceConfiguration is a configuration of a USB Mass Storage storage device.
//
// This device configuration creates a storage device that conforms to the USB Mass Storage specification.
//
// see: https://developer.apple.com/documentation/virtualization/vzusbmassstoragedeviceconfiguration?language=objc
type USBMassStorageDeviceConfiguration struct {
*pointer
*baseStorageDeviceConfiguration
// marking as currently reachable.
// This ensures that the object is not freed, and its finalizer is not run
attachment StorageDeviceAttachment
}
// NewUSBMassStorageDeviceConfiguration initialize a USBMassStorageDeviceConfiguration
// with a device attachment.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func NewUSBMassStorageDeviceConfiguration(attachment StorageDeviceAttachment) (*USBMassStorageDeviceConfiguration, error) {
if err := macOSAvailable(13); err != nil {
return nil, err
}
usbMass := &USBMassStorageDeviceConfiguration{
pointer: objc.NewPointer(
C.newVZUSBMassStorageDeviceConfiguration(objc.Ptr(attachment)),
),
attachment: attachment,
}
objc.SetFinalizer(usbMass, func(self *USBMassStorageDeviceConfiguration) {
objc.Release(self)
})
return usbMass, nil
}

View File

@@ -0,0 +1,345 @@
package vz
/*
#cgo darwin CFLAGS: -mmacosx-version-min=11 -x objective-c -fno-objc-arc
#cgo darwin LDFLAGS: -lobjc -framework Foundation -framework Virtualization -framework Cocoa
# include "virtualization_11.h"
# include "virtualization_12.h"
# include "virtualization_13.h"
*/
import "C"
import (
"runtime/cgo"
"sync"
"unsafe"
"github.com/Code-Hex/vz/v3/internal/objc"
)
func init() {
C.sharedApplication()
}
// VirtualMachineState represents execution state of the virtual machine.
//
//go:generate stringer -type=VirtualMachineState
type VirtualMachineState int
const (
// VirtualMachineStateStopped Initial state before the virtual machine is started.
VirtualMachineStateStopped VirtualMachineState = iota
// VirtualMachineStateRunning Running virtual machine.
VirtualMachineStateRunning
// VirtualMachineStatePaused A started virtual machine is paused.
// This state can only be transitioned from VirtualMachineStatePausing.
VirtualMachineStatePaused
// VirtualMachineStateError The virtual machine has encountered an internal error.
VirtualMachineStateError
// VirtualMachineStateStarting The virtual machine is configuring the hardware and starting.
VirtualMachineStateStarting
// VirtualMachineStatePausing The virtual machine is being paused.
// This is the intermediate state between VirtualMachineStateRunning and VirtualMachineStatePaused.
VirtualMachineStatePausing
// VirtualMachineStateResuming The virtual machine is being resumed.
// This is the intermediate state between VirtualMachineStatePaused and VirtualMachineStateRunning.
VirtualMachineStateResuming
// VZVirtualMachineStateStopping The virtual machine is being stopped.
// This is the intermediate state between VZVirtualMachineStateRunning and VZVirtualMachineStateStop.
VirtualMachineStateStopping
)
// VirtualMachine represents the entire state of a single virtual machine.
//
// A Virtual Machine is the emulation of a complete hardware machine of the same architecture as the real hardware machine.
// When executing the Virtual Machine, the Virtualization framework uses certain hardware resources and emulates others to provide isolation
// and great performance.
//
// The definition of a virtual machine starts with its configuration. This is done by setting up a VirtualMachineConfiguration struct.
// Once configured, the virtual machine can be started with (*VirtualMachine).Start() method.
//
// Creating a virtual machine using the Virtualization framework requires the app to have the "com.apple.security.virtualization" entitlement.
// see: https://developer.apple.com/documentation/virtualization/vzvirtualmachine?language=objc
type VirtualMachine struct {
// id for this struct.
id string
// Indicate whether or not virtualization is available.
//
// If virtualization is unavailable, no VirtualMachineConfiguration will validate.
// The validation error of the VirtualMachineConfiguration provides more information about why virtualization is unavailable.
supported bool
*pointer
dispatchQueue unsafe.Pointer
status cgo.Handle
mu sync.Mutex
}
type machineStatus struct {
state VirtualMachineState
stateNotify chan VirtualMachineState
mu sync.RWMutex
}
// NewVirtualMachine creates a new VirtualMachine with VirtualMachineConfiguration.
//
// The configuration must be valid. Validation can be performed at runtime with (*VirtualMachineConfiguration).Validate() method.
// The configuration is copied by the initializer.
//
// This is only supported on macOS 11 and newer, error will
// be returned on older versions.
func NewVirtualMachine(config *VirtualMachineConfiguration) (*VirtualMachine, error) {
if err := macOSAvailable(11); err != nil {
return nil, err
}
// should not call Free function for this string.
cs := (*char)(objc.GetUUID())
dispatchQueue := C.makeDispatchQueue(cs.CString())
status := cgo.NewHandle(&machineStatus{
state: VirtualMachineState(0),
stateNotify: make(chan VirtualMachineState),
})
v := &VirtualMachine{
id: cs.String(),
pointer: objc.NewPointer(
C.newVZVirtualMachineWithDispatchQueue(
objc.Ptr(config),
dispatchQueue,
unsafe.Pointer(&status),
),
),
dispatchQueue: dispatchQueue,
status: status,
}
objc.SetFinalizer(v, func(self *VirtualMachine) {
self.status.Delete()
objc.ReleaseDispatch(self.dispatchQueue)
objc.Release(self)
})
return v, nil
}
// SocketDevices return the list of socket devices configured on this virtual machine.
// Return an empty array if no socket device is configured.
//
// Since only NewVirtioSocketDeviceConfiguration is available in vz package,
// it will always return VirtioSocketDevice.
// see: https://developer.apple.com/documentation/virtualization/vzvirtualmachine/3656702-socketdevices?language=objc
func (v *VirtualMachine) SocketDevices() []*VirtioSocketDevice {
nsArray := objc.NewNSArray(
C.VZVirtualMachine_socketDevices(objc.Ptr(v)),
)
ptrs := nsArray.ToPointerSlice()
socketDevices := make([]*VirtioSocketDevice, len(ptrs))
for i, ptr := range ptrs {
socketDevices[i] = newVirtioSocketDevice(ptr, v.dispatchQueue)
}
return socketDevices
}
//export changeStateOnObserver
func changeStateOnObserver(state C.int, cgoHandlerPtr unsafe.Pointer) {
status := *(*cgo.Handle)(cgoHandlerPtr)
// I expected it will not cause panic.
// if caused panic, that's unexpected behavior.
v, _ := status.Value().(*machineStatus)
v.mu.Lock()
newState := VirtualMachineState(state)
v.state = newState
// for non-blocking
go func() { v.stateNotify <- newState }()
v.mu.Unlock()
}
// State represents execution state of the virtual machine.
func (v *VirtualMachine) State() VirtualMachineState {
// I expected it will not cause panic.
// if caused panic, that's unexpected behavior.
val, _ := v.status.Value().(*machineStatus)
val.mu.RLock()
defer val.mu.RUnlock()
return val.state
}
// StateChangedNotify gets notification is changed execution state of the virtual machine.
func (v *VirtualMachine) StateChangedNotify() <-chan VirtualMachineState {
// I expected it will not cause panic.
// if caused panic, that's unexpected behavior.
val, _ := v.status.Value().(*machineStatus)
val.mu.RLock()
defer val.mu.RUnlock()
return val.stateNotify
}
// CanStart returns true if the machine is in a state that can be started.
func (v *VirtualMachine) CanStart() bool {
return bool(C.vmCanStart(objc.Ptr(v), v.dispatchQueue))
}
// CanPause returns true if the machine is in a state that can be paused.
func (v *VirtualMachine) CanPause() bool {
return bool(C.vmCanPause(objc.Ptr(v), v.dispatchQueue))
}
// CanResume returns true if the machine is in a state that can be resumed.
func (v *VirtualMachine) CanResume() bool {
return (bool)(C.vmCanResume(objc.Ptr(v), v.dispatchQueue))
}
// CanRequestStop returns whether the machine is in a state where the guest can be asked to stop.
func (v *VirtualMachine) CanRequestStop() bool {
return (bool)(C.vmCanRequestStop(objc.Ptr(v), v.dispatchQueue))
}
// CanStop returns whether the machine is in a state that can be stopped.
//
// This is only supported on macOS 12 and newer, false will always be returned
// on older versions.
func (v *VirtualMachine) CanStop() bool {
if err := macOSAvailable(12); err != nil {
return false
}
return (bool)(C.vmCanStop(objc.Ptr(v), v.dispatchQueue))
}
//export virtualMachineCompletionHandler
func virtualMachineCompletionHandler(cgoHandlerPtr, errPtr unsafe.Pointer) {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
handler := cgoHandler.Value().(func(error))
if err := newNSError(errPtr); err != nil {
handler(err)
} else {
handler(nil)
}
}
func makeHandler() (func(error), chan error) {
ch := make(chan error, 1)
return func(err error) {
ch <- err
close(ch)
}, ch
}
type virtualMachineStartOptions struct {
macOSVirtualMachineStartOptionsPtr unsafe.Pointer
}
// VirtualMachineStartOption is an option for virtual machine start.
type VirtualMachineStartOption func(*virtualMachineStartOptions) error
// Start a virtual machine that is in either Stopped or Error state.
//
// If you want to listen status change events, use the "StateChangedNotify" method.
//
// If options are specified, also checks whether these options are
// available in use your macOS version available.
func (v *VirtualMachine) Start(opts ...VirtualMachineStartOption) error {
o := &virtualMachineStartOptions{}
for _, optFunc := range opts {
if err := optFunc(o); err != nil {
return err
}
}
h, errCh := makeHandler()
handler := cgo.NewHandle(h)
defer handler.Delete()
if o.macOSVirtualMachineStartOptionsPtr != nil {
C.startWithOptionsCompletionHandler(
objc.Ptr(v),
v.dispatchQueue,
o.macOSVirtualMachineStartOptionsPtr,
unsafe.Pointer(&handler),
)
} else {
C.startWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, unsafe.Pointer(&handler))
}
return <-errCh
}
// Pause a virtual machine that is in Running state.
//
// If you want to listen status change events, use the "StateChangedNotify" method.
func (v *VirtualMachine) Pause() error {
h, errCh := makeHandler()
handler := cgo.NewHandle(h)
defer handler.Delete()
C.pauseWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, unsafe.Pointer(&handler))
return <-errCh
}
// Resume a virtual machine that is in the Paused state.
//
// If you want to listen status change events, use the "StateChangedNotify" method.
func (v *VirtualMachine) Resume() error {
h, errCh := makeHandler()
handler := cgo.NewHandle(h)
defer handler.Delete()
C.resumeWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, unsafe.Pointer(&handler))
return <-errCh
}
// RequestStop requests that the guest turns itself off.
//
// If returned error is not nil, assigned with the error if the request failed.
// Returns true if the request was made successfully.
func (v *VirtualMachine) RequestStop() (bool, error) {
nserrPtr := newNSErrorAsNil()
ret := (bool)(C.requestStopVirtualMachine(objc.Ptr(v), v.dispatchQueue, &nserrPtr))
if err := newNSError(nserrPtr); err != nil {
return ret, err
}
return ret, nil
}
// Stop stops a VM thats in either a running or paused state.
//
// The completion handler returns an error object when the VM fails to stop,
// or nil if the stop was successful.
//
// If you want to listen status change events, use the "StateChangedNotify" method.
//
// Warning: This is a destructive operation. It stops the VM without
// giving the guest a chance to stop cleanly.
//
// This is only supported on macOS 12 and newer, error will be returned on older versions.
func (v *VirtualMachine) Stop() error {
if err := macOSAvailable(12); err != nil {
return err
}
h, errCh := makeHandler()
handler := cgo.NewHandle(h)
defer handler.Delete()
C.stopWithCompletionHandler(objc.Ptr(v), v.dispatchQueue, unsafe.Pointer(&handler))
return <-errCh
}
// StartGraphicApplication starts an application to display graphics of the VM.
//
// You must to call runtime.LockOSThread before calling this method.
//
// This is only supported on macOS 12 and newer, error will be returned on older versions.
func (v *VirtualMachine) StartGraphicApplication(width, height float64) error {
if err := macOSAvailable(12); err != nil {
return err
}
C.startVirtualMachineWindow(objc.Ptr(v), C.double(width), C.double(height))
return nil
}

View File

@@ -1,24 +1,29 @@
//
// virtualization.h
// virtualization_11.h
//
// Created by codehex.
//
#pragma once
#import <Foundation/Foundation.h>
#import "virtualization_helper.h"
#import <Virtualization/Virtualization.h>
/* exported from cgo */
void startHandler(void *err, char *id);
void pauseHandler(void *err, char *id);
void resumeHandler(void *err, char *id);
void changeStateOnObserver(int state, char *id);
void connectionHandler(void *connection, void *err, void *cgoHandlerPtr);
void changeStateOnObserver(int state, void *cgoHandler);
bool shouldAcceptNewConnectionHandler(void *cgoHandler, void *connection, void *socketDevice);
@interface Observer : NSObject
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
@end
/* VZVirtioSocketListener */
@interface VZVirtioSocketListenerDelegateImpl : NSObject <VZVirtioSocketListenerDelegate>
- (instancetype)initWithHandler:(void *)cgoHandler;
- (BOOL)listener:(VZVirtioSocketListener *)listener shouldAcceptNewConnection:(VZVirtioSocketConnection *)connection fromSocketDevice:(VZVirtioSocketDevice *)socketDevice;
@end
/* BootLoader */
void *newVZLinuxBootLoader(const char *kernelPath);
void setCommandLineVZLinuxBootLoader(void *bootLoaderPtr, const char *commandLine);
@@ -26,21 +31,27 @@ void setInitialRamdiskURLVZLinuxBootLoader(void *bootLoaderPtr, const char *ramd
/* VirtualMachineConfiguration */
bool validateVZVirtualMachineConfiguration(void *config, void **error);
unsigned long long minimumAllowedMemorySizeVZVirtualMachineConfiguration();
unsigned long long maximumAllowedMemorySizeVZVirtualMachineConfiguration();
unsigned int minimumAllowedCPUCountVZVirtualMachineConfiguration();
unsigned int maximumAllowedCPUCountVZVirtualMachineConfiguration();
void *newVZVirtualMachineConfiguration(void *bootLoader,
unsigned int CPUCount,
unsigned long long memorySize);
unsigned int CPUCount,
unsigned long long memorySize);
void setEntropyDevicesVZVirtualMachineConfiguration(void *config,
void *entropyDevices);
void *entropyDevices);
void setMemoryBalloonDevicesVZVirtualMachineConfiguration(void *config,
void *memoryBalloonDevices);
void *memoryBalloonDevices);
void setNetworkDevicesVZVirtualMachineConfiguration(void *config,
void *networkDevices);
void *networkDevices);
void *networkDevicesVZVirtualMachineConfiguration(void *config);
void setSerialPortsVZVirtualMachineConfiguration(void *config,
void *serialPorts);
void *serialPorts);
void setSocketDevicesVZVirtualMachineConfiguration(void *config,
void *socketDevices);
void *socketDevices);
void *socketDevicesVZVirtualMachineConfiguration(void *config);
void setStorageDevicesVZVirtualMachineConfiguration(void *config,
void *storageDevices);
void *storageDevices);
/* Configurations */
void *newVZFileHandleSerialPortAttachment(int readFileDescriptor, int writeFileDescriptor);
@@ -59,16 +70,30 @@ void *newVZVirtioSocketDeviceConfiguration();
void *newVZMACAddress(const char *macAddress);
void *newRandomLocallyAdministeredVZMACAddress();
const char *getVZMACAddressString(void *macAddress);
void *newVZVirtioSocketListener(void *cgoHandlerPtr);
void *VZVirtualMachine_socketDevices(void *machine);
void VZVirtioSocketDevice_setSocketListenerForPort(void *socketDevice, void *vmQueue, void *listener, uint32_t port);
void VZVirtioSocketDevice_removeSocketListenerForPort(void *socketDevice, void *vmQueue, uint32_t port);
void VZVirtioSocketDevice_connectToPort(void *socketDevice, void *vmQueue, uint32_t port, void *cgoHandlerPtr);
/* VirtualMachine */
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, const char *vmid);
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, void *statusHandler);
bool requestStopVirtualMachine(void *machine, void *queue, void **error);
void startWithCompletionHandler(void *machine, void *queue, const char *vmid);
void pauseWithCompletionHandler(void *machine, void *queue, const char *vmid);
void resumeWithCompletionHandler(void *machine, void *queue, const char *vmid);
void startWithCompletionHandler(void *machine, void *queue, void *completionHandler);
void pauseWithCompletionHandler(void *machine, void *queue, void *completionHandler);
void resumeWithCompletionHandler(void *machine, void *queue, void *completionHandler);
bool vmCanStart(void *machine, void *queue);
bool vmCanPause(void *machine, void *queue);
bool vmCanResume(void *machine, void *queue);
bool vmCanRequestStop(void *machine, void *queue);
void *makeDispatchQueue(const char *label);
void *makeDispatchQueue(const char *label);
/* VZVirtioSocketConnection */
typedef struct VZVirtioSocketConnectionFlat {
uint32_t destinationPort;
uint32_t sourcePort;
int fileDescriptor;
} VZVirtioSocketConnectionFlat;
VZVirtioSocketConnectionFlat convertVZVirtioSocketConnection2Flat(void *connection);

View File

@@ -0,0 +1,887 @@
//
// virtualization_11.m
//
// Created by codehex.
//
#import "virtualization_11.h"
char *copyCString(NSString *nss)
{
const char *cc = [nss UTF8String];
char *c = calloc([nss length] + 1, 1);
strncpy(c, cc, [nss length]);
return c;
}
@implementation Observer
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
{
@autoreleasepool {
if ([keyPath isEqualToString:@"state"]) {
int newState = (int)[change[NSKeyValueChangeNewKey] integerValue];
changeStateOnObserver(newState, context);
} else {
// bool canVal = (bool)[change[NSKeyValueChangeNewKey] boolValue];
// char *vmid = copyCString((NSString *)context);
// char *key = copyCString(keyPath);
// changeCanPropertyOnObserver(canVal, vmid, key);
// free(vmid);
// free(key);
}
}
}
@end
@implementation VZVirtioSocketListenerDelegateImpl {
void *_cgoHandler;
}
- (instancetype)initWithHandler:(void *)cgoHandler
{
self = [super init];
_cgoHandler = cgoHandler;
return self;
}
- (BOOL)listener:(VZVirtioSocketListener *)listener shouldAcceptNewConnection:(VZVirtioSocketConnection *)connection fromSocketDevice:(VZVirtioSocketDevice *)socketDevice;
{
return (BOOL)shouldAcceptNewConnectionHandler(_cgoHandler, connection, socketDevice);
}
@end
/*!
@abstract Create a VZLinuxBootLoader with the Linux kernel passed as URL.
@param kernelPath Path of Linux kernel on the local file system.
*/
void *newVZLinuxBootLoader(const char *kernelPath)
{
if (@available(macOS 11, *)) {
NSString *kernelPathNSString = [NSString stringWithUTF8String:kernelPath];
NSURL *kernelURL = [NSURL fileURLWithPath:kernelPathNSString];
return [[VZLinuxBootLoader alloc] initWithKernelURL:kernelURL];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the command-line parameters.
@param bootLoader VZLinuxBootLoader
@param commandLine The command-line parameters passed to the kernel on boot.
@link https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
*/
void setCommandLineVZLinuxBootLoader(void *bootLoaderPtr, const char *commandLine)
{
if (@available(macOS 11, *)) {
NSString *commandLineNSString = [NSString stringWithUTF8String:commandLine];
[(VZLinuxBootLoader *)bootLoaderPtr setCommandLine:commandLineNSString];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the optional initial RAM disk.
@param bootLoader VZLinuxBootLoader
@param ramdiskPath The RAM disk is mapped into memory before booting the kernel.
@link https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
*/
void setInitialRamdiskURLVZLinuxBootLoader(void *bootLoaderPtr, const char *ramdiskPath)
{
if (@available(macOS 11, *)) {
NSString *ramdiskPathNSString = [NSString stringWithUTF8String:ramdiskPath];
NSURL *ramdiskURL = [NSURL fileURLWithPath:ramdiskPathNSString];
[(VZLinuxBootLoader *)bootLoaderPtr setInitialRamdiskURL:ramdiskURL];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Validate the configuration.
@param config Virtual machine configuration.
@param error If not nil, assigned with the validation error if the validation failed.
@return true if the configuration is valid.
*/
bool validateVZVirtualMachineConfiguration(void *config, void **error)
{
if (@available(macOS 11, *)) {
return (bool)[(VZVirtualMachineConfiguration *)config
validateWithError:(NSError *_Nullable *_Nullable)error];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract: Minimum amount of memory required by virtual machines.
@see VZVirtualMachineConfiguration.memorySize
*/
unsigned long long minimumAllowedMemorySizeVZVirtualMachineConfiguration()
{
if (@available(macOS 11, *)) {
return (unsigned long long)[VZVirtualMachineConfiguration minimumAllowedMemorySize];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract: Maximum amount of memory allowed for a virtual machine.
@see VZVirtualMachineConfiguration.memorySize
*/
unsigned long long maximumAllowedMemorySizeVZVirtualMachineConfiguration()
{
if (@available(macOS 11, *)) {
return (unsigned long long)[VZVirtualMachineConfiguration maximumAllowedMemorySize];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract: Minimum number of CPUs for a virtual machine.
@see VZVirtualMachineConfiguration.CPUCount
*/
unsigned int minimumAllowedCPUCountVZVirtualMachineConfiguration()
{
if (@available(macOS 11, *)) {
return (unsigned int)[VZVirtualMachineConfiguration minimumAllowedCPUCount];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract: Maximum number of CPUs for a virtual machine.
@see VZVirtualMachineConfiguration.CPUCount
*/
unsigned int maximumAllowedCPUCountVZVirtualMachineConfiguration()
{
if (@available(macOS 11, *)) {
return (unsigned int)[VZVirtualMachineConfiguration maximumAllowedCPUCount];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a new Virtual machine configuration.
@param bootLoader Boot loader used when the virtual machine starts.
@param CPUCount Number of CPUs.
@discussion
The number of CPUs must be a value between VZVirtualMachineConfiguration.minimumAllowedCPUCount
and VZVirtualMachineConfiguration.maximumAllowedCPUCount.
@see VZVirtualMachineConfiguration.minimumAllowedCPUCount
@see VZVirtualMachineConfiguration.maximumAllowedCPUCount
@param memorySize Virtual machine memory size in bytes.
@discussion
The memory size must be a multiple of a 1 megabyte (1024 * 1024 bytes) between VZVirtualMachineConfiguration.minimumAllowedMemorySize
and VZVirtualMachineConfiguration.maximumAllowedMemorySize.
The memorySize represents the total physical memory seen by a guest OS running in the virtual machine.
Not all memory is allocated on start, the virtual machine allocates memory on demand.
@see VZVirtualMachineConfiguration.minimumAllowedMemorySize
@see VZVirtualMachineConfiguration.maximumAllowedMemorySize
*/
void *newVZVirtualMachineConfiguration(void *bootLoaderPtr,
unsigned int CPUCount,
unsigned long long memorySize)
{
if (@available(macOS 11, *)) {
VZVirtualMachineConfiguration *config = [[VZVirtualMachineConfiguration alloc] init];
[config setBootLoader:(VZLinuxBootLoader *)bootLoaderPtr];
[config setCPUCount:(NSUInteger)CPUCount];
[config setMemorySize:memorySize];
return config;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of entropy devices. Empty by default.
@see VZVirtioEntropyDeviceConfiguration
*/
void setEntropyDevicesVZVirtualMachineConfiguration(void *config,
void *entropyDevices)
{
if (@available(macOS 11, *)) {
[(VZVirtualMachineConfiguration *)config setEntropyDevices:[(NSMutableArray *)entropyDevices copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of memory balloon devices. Empty by default.
@see VZVirtioTraditionalMemoryBalloonDeviceConfiguration
*/
void setMemoryBalloonDevicesVZVirtualMachineConfiguration(void *config,
void *memoryBalloonDevices)
{
if (@available(macOS 11, *)) {
[(VZVirtualMachineConfiguration *)config setMemoryBalloonDevices:[(NSMutableArray *)memoryBalloonDevices copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of network adapters. Empty by default.
@see VZVirtioNetworkDeviceConfiguration
*/
void setNetworkDevicesVZVirtualMachineConfiguration(void *config,
void *networkDevices)
{
if (@available(macOS 11, *)) {
[(VZVirtualMachineConfiguration *)config setNetworkDevices:[(NSMutableArray *)networkDevices copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Return the list of network devices configurations for this VZVirtualMachineConfiguration. Return an empty array if no network device configuration is set.
*/
void *networkDevicesVZVirtualMachineConfiguration(void *config)
{
if (@available(macOS 11, *)) {
return [(VZVirtualMachineConfiguration *)config networkDevices]; // NSArray<VZSocketDeviceConfiguration *>
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of serial ports. Empty by default.
@see VZVirtioConsoleDeviceSerialPortConfiguration
*/
void setSerialPortsVZVirtualMachineConfiguration(void *config,
void *serialPorts)
{
if (@available(macOS 11, *)) {
[(VZVirtualMachineConfiguration *)config setSerialPorts:[(NSMutableArray *)serialPorts copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of socket devices. Empty by default.
@see VZVirtioSocketDeviceConfiguration
*/
void setSocketDevicesVZVirtualMachineConfiguration(void *config,
void *socketDevices)
{
if (@available(macOS 11, *)) {
[(VZVirtualMachineConfiguration *)config setSocketDevices:[(NSMutableArray *)socketDevices copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Return the list of socket devices configurations for this VZVirtualMachineConfiguration. Return an empty array if no socket device configuration is set.
*/
void *socketDevicesVZVirtualMachineConfiguration(void *config)
{
if (@available(macOS 11, *)) {
return [(VZVirtualMachineConfiguration *)config socketDevices]; // NSArray<VZSocketDeviceConfiguration *>
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of disk devices. Empty by default.
@see VZVirtioBlockDeviceConfiguration
*/
void setStorageDevicesVZVirtualMachineConfiguration(void *config,
void *storageDevices)
{
if (@available(macOS 11, *)) {
[(VZVirtualMachineConfiguration *)config setStorageDevices:[(NSMutableArray *)storageDevices copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Intialize the VZFileHandleSerialPortAttachment from file descriptors.
@param readFileDescriptor File descriptor for reading from the file.
@param writeFileDescriptor File descriptor for writing to the file.
@discussion
Each file descriptor must a valid.
*/
void *newVZFileHandleSerialPortAttachment(int readFileDescriptor, int writeFileDescriptor)
{
if (@available(macOS 11, *)) {
VZFileHandleSerialPortAttachment *ret;
@autoreleasepool {
NSFileHandle *fileHandleForReading = [[NSFileHandle alloc] initWithFileDescriptor:readFileDescriptor];
NSFileHandle *fileHandleForWriting = [[NSFileHandle alloc] initWithFileDescriptor:writeFileDescriptor];
ret = [[VZFileHandleSerialPortAttachment alloc]
initWithFileHandleForReading:fileHandleForReading
fileHandleForWriting:fileHandleForWriting];
}
return ret;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize the VZFileSerialPortAttachment from a URL of a file.
@param filePath The path of the file for the attachment on the local file system.
@param shouldAppend True if the file should be opened in append mode, false otherwise.
When a file is opened in append mode, writing to that file will append to the end of it.
@param error If not nil, used to report errors if initialization fails.
@return A VZFileSerialPortAttachment on success. Nil otherwise and the error parameter is populated if set.
*/
void *newVZFileSerialPortAttachment(const char *filePath, bool shouldAppend, void **error)
{
if (@available(macOS 11, *)) {
NSString *filePathNSString = [NSString stringWithUTF8String:filePath];
NSURL *fileURL = [NSURL fileURLWithPath:filePathNSString];
return [[VZFileSerialPortAttachment alloc]
initWithURL:fileURL
append:(BOOL)shouldAppend
error:(NSError *_Nullable *_Nullable)error];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a new Virtio Console Serial Port Device configuration
@param attachment Base class for a serial port attachment.
@discussion
The device creates a console which enables communication between the host and the guest through the Virtio interface.
The device sets up a single port on the Virtio console device.
*/
void *newVZVirtioConsoleDeviceSerialPortConfiguration(void *attachment)
{
if (@available(macOS 11, *)) {
VZVirtioConsoleDeviceSerialPortConfiguration *config = [[VZVirtioConsoleDeviceSerialPortConfiguration alloc] init];
[config setAttachment:(VZSerialPortAttachment *)attachment];
return config;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a new Network device attachment bridging a host physical interface with a virtual network device.
@param networkInterface a network interface that bridges a physical interface.
@discussion
A bridged network allows the virtual machine to use the same physical interface as the host. Both host and virtual machine
send and receive packets on the same physical interface but have distinct network layers.
The bridge network device attachment is used with a VZNetworkDeviceConfiguration to define a virtual network device.
Using a VZBridgedNetworkDeviceAttachment requires the app to have the "com.apple.vm.networking" entitlement.
@see VZBridgedNetworkInterface
@see VZNetworkDeviceConfiguration
@see VZVirtioNetworkDeviceConfiguration
*/
void *newVZBridgedNetworkDeviceAttachment(void *networkInterface)
{
if (@available(macOS 11, *)) {
return [[VZBridgedNetworkDeviceAttachment alloc] initWithInterface:(VZBridgedNetworkInterface *)networkInterface];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a new Network device attachment using network address translation (NAT) with outside networks.
@discussion
Using the NAT attachment type, the host serves as router and performs network address translation for accesses to outside networks.
@see VZNetworkDeviceConfiguration
@see VZVirtioNetworkDeviceConfiguration
*/
void *newVZNATNetworkDeviceAttachment()
{
if (@available(macOS 11, *)) {
return [[VZNATNetworkDeviceAttachment alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a new Network device attachment sending raw network packets over a file handle.
@discussion
The file handle attachment transmits the raw packets/frames between the virtual network interface and a file handle.
The data transmitted through this attachment is at the level of the data link layer.
The file handle must hold a connected datagram socket.
@see VZNetworkDeviceConfiguration
@see VZVirtioNetworkDeviceConfiguration
*/
void *newVZFileHandleNetworkDeviceAttachment(int fileDescriptor)
{
if (@available(macOS 11, *)) {
VZFileHandleNetworkDeviceAttachment *ret;
@autoreleasepool {
NSFileHandle *fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileDescriptor];
ret = [[VZFileHandleNetworkDeviceAttachment alloc] initWithFileHandle:fileHandle];
}
return ret;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a new Configuration of a paravirtualized network device of type Virtio Network Device.
@discussion
The communication channel used on the host is defined through the attachment. It is set with the VZNetworkDeviceConfiguration.attachment property.
The configuration is only valid with valid MACAddress and attachment.
@see VZVirtualMachineConfiguration.networkDevices
@param attachment Base class for a network device attachment.
@discussion
A network device attachment defines how a virtual network device interfaces with the host system.
VZNetworkDeviceAttachment should not be instantiated directly. One of its subclasses should be used instead.
Common attachment types include:
- VZNATNetworkDeviceAttachment
- VZFileHandleNetworkDeviceAttachment
@see VZBridgedNetworkDeviceAttachment
@see VZFileHandleNetworkDeviceAttachment
@see VZNATNetworkDeviceAttachment
*/
void *newVZVirtioNetworkDeviceConfiguration(void *attachment)
{
if (@available(macOS 11, *)) {
VZVirtioNetworkDeviceConfiguration *config = [[VZVirtioNetworkDeviceConfiguration alloc] init];
[config setAttachment:(VZNetworkDeviceAttachment *)attachment];
return config;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a new Virtio Entropy Device confiuration
@discussion The device exposes a source of entropy for the guest's random number generator.
*/
void *newVZVirtioEntropyDeviceConfiguration()
{
if (@available(macOS 11, *)) {
return [[VZVirtioEntropyDeviceConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a VZVirtioBlockDeviceConfiguration with a device attachment.
@param attachment The storage device attachment. This defines how the virtualized device operates on the host side.
@see VZDiskImageStorageDeviceAttachment
*/
void *newVZVirtioBlockDeviceConfiguration(void *attachment)
{
if (@available(macOS 11, *)) {
return [[VZVirtioBlockDeviceConfiguration alloc] initWithAttachment:(VZStorageDeviceAttachment *)attachment];
}
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 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 *newVZDiskImageStorageDeviceAttachment(const char *diskPath, bool readOnly, void **error)
{
if (@available(macOS 11, *)) {
NSString *diskPathNSString = [NSString stringWithUTF8String:diskPath];
NSURL *diskURL = [NSURL fileURLWithPath:diskPathNSString];
return [[VZDiskImageStorageDeviceAttachment alloc]
initWithURL:diskURL
readOnly:(BOOL)readOnly
error:(NSError *_Nullable *_Nullable)error];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a configuration of the Virtio traditional memory balloon device.
@discussion
This configuration creates a Virtio traditional memory balloon device which allows for managing guest memory.
Only one Virtio traditional memory balloon device can be used per virtual machine.
@see VZVirtioTraditionalMemoryBalloonDevice
*/
void *newVZVirtioTraditionalMemoryBalloonDeviceConfiguration()
{
if (@available(macOS 11, *)) {
return [[VZVirtioTraditionalMemoryBalloonDeviceConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a configuration of the Virtio socket device.
@discussion
This configuration creates a Virtio socket device for the guest which communicates with the host through the Virtio interface.
Only one Virtio socket device can be used per virtual machine.
@see VZVirtioSocketDevice
*/
void *newVZVirtioSocketDeviceConfiguration()
{
if (@available(macOS 11, *)) {
return [[VZVirtioSocketDeviceConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract The VZVirtioSocketListener object represents a listener for the Virtio socket device.
@discussion
The listener encompasses a VZVirtioSocketListenerDelegate object.
VZVirtioSocketListener is used with VZVirtioSocketDevice to listen to a particular port.
The delegate is used when a guest connects to a port associated with the listener.
@see VZVirtioSocketDevice
@see VZVirtioSocketListenerDelegate
*/
void *newVZVirtioSocketListener(void *cgoHandlerPtr)
{
if (@available(macOS 11, *)) {
VZVirtioSocketListener *ret = [[VZVirtioSocketListener alloc] init];
[ret setDelegate:[[VZVirtioSocketListenerDelegateImpl alloc] initWithHandler:cgoHandlerPtr]];
return ret;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Sets a listener at a specified port.
@discussion
There is only one listener per port, any existing listener will be removed, and the specified listener here will be set instead.
The same listener can be registered on multiple ports.
The listener's delegate will be called whenever the guest connects to that port.
@param listener The VZVirtioSocketListener object to be set.
@param port The port number to set the listener at.
*/
void VZVirtioSocketDevice_setSocketListenerForPort(void *socketDevice, void *vmQueue, void *listener, uint32_t port)
{
if (@available(macOS 11, *)) {
dispatch_sync((dispatch_queue_t)vmQueue, ^{
[(VZVirtioSocketDevice *)socketDevice setSocketListener:(VZVirtioSocketListener *)listener forPort:port];
});
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Removes the listener at a specfied port.
@discussion Does nothing if the port had no listener.
@param port The port number at which the listener is to be removed.
*/
void VZVirtioSocketDevice_removeSocketListenerForPort(void *socketDevice, void *vmQueue, uint32_t port)
{
if (@available(macOS 11, *)) {
dispatch_sync((dispatch_queue_t)vmQueue, ^{
[(VZVirtioSocketDevice *)socketDevice removeSocketListenerForPort:port];
});
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Connects to a specified port.
@discussion Does nothing if the guest does not listen on that port.
@param port The port number to connect to.
@param completionHandler Block called after the connection has been successfully established or on error.
The error parameter passed to the block is nil if the connection was successful.
*/
void VZVirtioSocketDevice_connectToPort(void *socketDevice, void *vmQueue, uint32_t port, void *cgoHandlerPtr)
{
if (@available(macOS 11, *)) {
dispatch_async((dispatch_queue_t)vmQueue, ^{
[(VZVirtioSocketDevice *)socketDevice connectToPort:port
completionHandler:^(VZVirtioSocketConnection *connection, NSError *err) {
connectionHandler(connection, err, cgoHandlerPtr);
}];
});
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
VZVirtioSocketConnectionFlat convertVZVirtioSocketConnection2Flat(void *connection)
{
if (@available(macOS 11, *)) {
VZVirtioSocketConnectionFlat ret;
ret.sourcePort = [(VZVirtioSocketConnection *)connection sourcePort];
ret.destinationPort = [(VZVirtioSocketConnection *)connection destinationPort];
ret.fileDescriptor = [(VZVirtioSocketConnection *)connection fileDescriptor];
return ret;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize the virtual machine.
@param config The configuration of the virtual machine.
The configuration must be valid. Validation can be performed at runtime with [VZVirtualMachineConfiguration validateWithError:].
The configuration is copied by the initializer.
@param queue The serial queue on which the virtual machine operates.
Every operation on the virtual machine must be done on that queue. The callbacks and delegate methods are invoked on that queue.
If the queue is not serial, the behavior is undefined.
*/
void *newVZVirtualMachineWithDispatchQueue(void *config, void *queue, void *statusHandler)
{
if (@available(macOS 11, *)) {
VZVirtualMachine *vm = [[VZVirtualMachine alloc]
initWithConfiguration:(VZVirtualMachineConfiguration *)config
queue:(dispatch_queue_t)queue];
@autoreleasepool {
Observer *o = [[Observer alloc] init];
[vm addObserver:o
forKeyPath:@"state"
options:NSKeyValueObservingOptionNew
context:statusHandler];
}
return vm;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Return the list of socket devices configured on this virtual machine. Return an empty array if no socket device is configured.
@see VZVirtioSocketDeviceConfiguration
@see VZVirtualMachineConfiguration
*/
void *VZVirtualMachine_socketDevices(void *machine)
{
if (@available(macOS 11, *)) {
return [(VZVirtualMachine *)machine socketDevices]; // NSArray<VZSocketDevice *>
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize the VZMACAddress from a string representation of a MAC address.
@param string
The string should be formatted representing the 6 bytes in hexadecimal separated by a colon character.
e.g. "01:23:45:ab:cd:ef"
The alphabetical characters can appear lowercase or uppercase.
@return A VZMACAddress or nil if the string is not formatted correctly.
*/
void *newVZMACAddress(const char *macAddress)
{
if (@available(macOS 11, *)) {
NSString *str = [NSString stringWithUTF8String:macAddress];
return [[VZMACAddress alloc] initWithString:str];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a valid, random, unicast, locally administered address.
@discussion The generated address is not guaranteed to be unique.
*/
void *newRandomLocallyAdministeredVZMACAddress()
{
if (@available(macOS 11, *)) {
return [VZMACAddress randomLocallyAdministeredAddress];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Sets the media access control address of the device.
*/
void setNetworkDevicesVZMACAddress(void *config, void *macAddress)
{
if (@available(macOS 11, *)) {
[(VZNetworkDeviceConfiguration *)config setMACAddress:[(VZMACAddress *)macAddress copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract The address represented as a string.
@discussion
The 6 bytes are represented in hexadecimal form, separated by a colon character.
Alphabetical characters are lowercase.
The address is compatible with the parameter of -[VZMACAddress initWithString:].
*/
const char *getVZMACAddressString(void *macAddress)
{
if (@available(macOS 11, *)) {
return [[(VZMACAddress *)macAddress string] UTF8String];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Request that the guest turns itself off.
@param error If not nil, assigned with the error if the request failed.
@return YES if the request was made successfully.
*/
bool requestStopVirtualMachine(void *machine, void *queue, void **error)
{
if (@available(macOS 11, *)) {
__block BOOL ret;
dispatch_sync((dispatch_queue_t)queue, ^{
ret = [(VZVirtualMachine *)machine requestStopWithError:(NSError *_Nullable *_Nullable)error];
});
return (bool)ret;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void *makeDispatchQueue(const char *label)
{
// dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0);
dispatch_queue_t queue = dispatch_queue_create(label, DISPATCH_QUEUE_SERIAL);
// dispatch_retain(queue);
return queue;
}
void startWithCompletionHandler(void *machine, void *queue, void *completionHandler)
{
if (@available(macOS 11, *)) {
vm_completion_handler_t handler = makeVMCompletionHandler(completionHandler);
dispatch_sync((dispatch_queue_t)queue, ^{
[(VZVirtualMachine *)machine startWithCompletionHandler:handler];
});
Block_release(handler);
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void pauseWithCompletionHandler(void *machine, void *queue, void *completionHandler)
{
if (@available(macOS 11, *)) {
vm_completion_handler_t handler = makeVMCompletionHandler(completionHandler);
dispatch_sync((dispatch_queue_t)queue, ^{
[(VZVirtualMachine *)machine pauseWithCompletionHandler:handler];
});
Block_release(handler);
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void resumeWithCompletionHandler(void *machine, void *queue, void *completionHandler)
{
if (@available(macOS 11, *)) {
vm_completion_handler_t handler = makeVMCompletionHandler(completionHandler);
dispatch_sync((dispatch_queue_t)queue, ^{
[(VZVirtualMachine *)machine resumeWithCompletionHandler:handler];
});
Block_release(handler);
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
// TODO(codehex): use KVO
bool vmCanStart(void *machine, void *queue)
{
if (@available(macOS 11, *)) {
__block BOOL result;
dispatch_sync((dispatch_queue_t)queue, ^{
result = ((VZVirtualMachine *)machine).canStart;
});
return (bool)result;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
bool vmCanPause(void *machine, void *queue)
{
if (@available(macOS 11, *)) {
__block BOOL result;
dispatch_sync((dispatch_queue_t)queue, ^{
result = ((VZVirtualMachine *)machine).canPause;
});
return (bool)result;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
bool vmCanResume(void *machine, void *queue)
{
if (@available(macOS 11, *)) {
__block BOOL result;
dispatch_sync((dispatch_queue_t)queue, ^{
result = ((VZVirtualMachine *)machine).canResume;
});
return (bool)result;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
bool vmCanRequestStop(void *machine, void *queue)
{
if (@available(macOS 11, *)) {
__block BOOL result;
dispatch_sync((dispatch_queue_t)queue, ^{
result = ((VZVirtualMachine *)machine).canRequestStop;
});
return (bool)result;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
// --- TODO end

View File

@@ -0,0 +1,48 @@
//
// virtualization_12.h
//
// Created by codehex.
//
#import "virtualization_helper.h"
#import "virtualization_view.h"
// FIXME(codehex): this is dirty hack to avoid clang-format error like below
// "Configuration file(s) do(es) not support C++: /github.com/Code-Hex/vz/.clang-format"
#define NSURLComponents NSURLComponents
bool vmCanStop(void *machine, void *queue);
void stopWithCompletionHandler(void *machine, void *queue, void *completionHandler);
void *newVZGenericPlatformConfiguration();
void *newVZVirtioSoundDeviceInputStreamConfiguration();
void *newVZVirtioSoundDeviceHostInputStreamConfiguration(); // use in Go
void *newVZVirtioSoundDeviceOutputStreamConfiguration();
void *newVZVirtioSoundDeviceHostOutputStreamConfiguration(); // use in Go
void *newVZUSBScreenCoordinatePointingDeviceConfiguration();
void *newVZUSBKeyboardConfiguration();
void *newVZVirtioSoundDeviceConfiguration();
void setStreamsVZVirtioSoundDeviceConfiguration(void *audioDeviceConfiguration, void *streams);
void *newVZSharedDirectory(const char *dirPath, bool readOnly);
void *newVZSingleDirectoryShare(void *sharedDirectory);
void *newVZMultipleDirectoryShare(void *sharedDirectories);
void *newVZVirtioFileSystemDeviceConfiguration(const char *tag, void **error);
void setVZVirtioFileSystemDeviceConfigurationShare(void *config, void *share);
void setDirectorySharingDevicesVZVirtualMachineConfiguration(void *config, void *directorySharingDevices);
void setPlatformVZVirtualMachineConfiguration(void *config,
void *platform);
void setGraphicsDevicesVZVirtualMachineConfiguration(void *config,
void *graphicsDevices);
void setPointingDevicesVZVirtualMachineConfiguration(void *config,
void *pointingDevices);
void setKeyboardsVZVirtualMachineConfiguration(void *config,
void *keyboards);
void setAudioDevicesVZVirtualMachineConfiguration(void *config,
void *audioDevices);
void sharedApplication();
void startVirtualMachineWindow(void *machine, double width, double height);

View File

@@ -0,0 +1,344 @@
//
// virtualization_12.m
//
// Created by codehex.
//
#import "virtualization_12.h"
bool vmCanStop(void *machine, void *queue)
{
if (@available(macOS 12, *)) {
__block BOOL result;
dispatch_sync((dispatch_queue_t)queue, ^{
result = ((VZVirtualMachine *)machine).canStop;
});
return (bool)result;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void stopWithCompletionHandler(void *machine, void *queue, void *completionHandler)
{
if (@available(macOS 12, *)) {
vm_completion_handler_t handler = makeVMCompletionHandler(completionHandler);
dispatch_sync((dispatch_queue_t)queue, ^{
[(VZVirtualMachine *)machine stopWithCompletionHandler:handler];
});
Block_release(handler);
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract The platform configuration for a generic Intel or ARM virtual machine.
*/
void *newVZGenericPlatformConfiguration()
{
if (@available(macOS 12, *)) {
return [[VZGenericPlatformConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of directory sharing devices. Empty by default.
@see VZDirectorySharingDeviceConfiguration
*/
void setDirectorySharingDevicesVZVirtualMachineConfiguration(void *config, void *directorySharingDevices)
{
if (@available(macOS 12, *)) {
[(VZVirtualMachineConfiguration *)config setDirectorySharingDevices:[(NSMutableArray *)directorySharingDevices copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract The hardware platform to use.
@discussion
Can be an instance of a VZGenericPlatformConfiguration or VZMacPlatformConfiguration. Defaults to VZGenericPlatformConfiguration.
*/
void setPlatformVZVirtualMachineConfiguration(void *config, void *platform)
{
if (@available(macOS 12, *)) {
[(VZVirtualMachineConfiguration *)config setPlatform:(VZPlatformConfiguration *)platform];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of graphics devices. Empty by default.
@see VZMacGraphicsDeviceConfiguration
*/
void setGraphicsDevicesVZVirtualMachineConfiguration(void *config, void *graphicsDevices)
{
if (@available(macOS 12, *)) {
[(VZVirtualMachineConfiguration *)config setGraphicsDevices:[(NSMutableArray *)graphicsDevices copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of pointing devices. Empty by default.
@see VZUSBScreenCoordinatePointingDeviceConfiguration
*/
void setPointingDevicesVZVirtualMachineConfiguration(void *config, void *pointingDevices)
{
if (@available(macOS 12, *)) {
[(VZVirtualMachineConfiguration *)config setPointingDevices:[(NSMutableArray *)pointingDevices copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of keyboards. Empty by default.
@see VZUSBKeyboardConfiguration
*/
void setKeyboardsVZVirtualMachineConfiguration(void *config, void *keyboards)
{
if (@available(macOS 12, *)) {
[(VZVirtualMachineConfiguration *)config setKeyboards:[(NSMutableArray *)keyboards copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract List of audio devices. Empty by default.
@see VZVirtioSoundDeviceConfiguration
*/
void setAudioDevicesVZVirtualMachineConfiguration(void *config, void *audioDevices)
{
if (@available(macOS 12, *)) {
[(VZVirtualMachineConfiguration *)config setAudioDevices:[(NSMutableArray *)audioDevices copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a new Virtio Sound Device Configuration.
@discussion The device exposes a source or destination of sound.
*/
void *newVZVirtioSoundDeviceConfiguration()
{
if (@available(macOS 12, *)) {
return [[VZVirtioSoundDeviceConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the list of audio streams exposed by this device. Empty by default.
*/
void setStreamsVZVirtioSoundDeviceConfiguration(void *audioDeviceConfiguration, void *streams)
{
if (@available(macOS 12, *)) {
[(VZVirtioSoundDeviceConfiguration *)audioDeviceConfiguration setStreams:[(NSMutableArray *)streams copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a new Virtio Sound Device Input Stream Configuration.
@discussion A PCM stream of input audio data, such as from a microphone.
*/
void *newVZVirtioSoundDeviceInputStreamConfiguration()
{
if (@available(macOS 12, *)) {
return [[VZVirtioSoundDeviceInputStreamConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a new Virtio Sound Device Host Audio Input Stream Configuration.
*/
void *newVZVirtioSoundDeviceHostInputStreamConfiguration()
{
if (@available(macOS 12, *)) {
VZVirtioSoundDeviceInputStreamConfiguration *inputStream = (VZVirtioSoundDeviceInputStreamConfiguration *)newVZVirtioSoundDeviceInputStreamConfiguration();
[inputStream setSource:[[VZHostAudioInputStreamSource alloc] init]];
return inputStream;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a new Virtio Sound Device Output Stream Configuration.
@discussion A PCM stream of output audio data, such as to a speaker.
*/
void *newVZVirtioSoundDeviceOutputStreamConfiguration()
{
if (@available(macOS 12, *)) {
return [[VZVirtioSoundDeviceOutputStreamConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a new Virtio Sound Device Host Audio Output Stream Configuration.
*/
void *newVZVirtioSoundDeviceHostOutputStreamConfiguration()
{
if (@available(macOS 12, *)) {
VZVirtioSoundDeviceOutputStreamConfiguration *outputStream = (VZVirtioSoundDeviceOutputStreamConfiguration *)newVZVirtioSoundDeviceOutputStreamConfiguration();
[outputStream setSink:[[VZHostAudioOutputStreamSink alloc] init]];
return outputStream;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize the VZSharedDirectory from the directory path and read only option.
@param dirPath
The directory path that will be share.
@param readOnly
If the directory should be mounted read only.
@return A VZSharedDirectory
*/
void *newVZSharedDirectory(const char *dirPath, bool readOnly)
{
if (@available(macOS 12, *)) {
NSString *dirPathNSString = [NSString stringWithUTF8String:dirPath];
NSURL *dirURL = [NSURL fileURLWithPath:dirPathNSString];
return [[VZSharedDirectory alloc] initWithURL:dirURL readOnly:(BOOL)readOnly];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize the VZSingleDirectoryShare from the shared directory.
@param sharedDirectory
The shared directory to use.
@return A VZSingleDirectoryShare
*/
void *newVZSingleDirectoryShare(void *sharedDirectory)
{
if (@available(macOS 12, *)) {
return [[VZSingleDirectoryShare alloc] initWithDirectory:(VZSharedDirectory *)sharedDirectory];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize the VZMultipleDirectoryShare from the shared directories.
@param sharedDirectories
NSDictionary mapping names to shared directories.
@return A VZMultipleDirectoryShare
*/
void *newVZMultipleDirectoryShare(void *sharedDirectories)
{
if (@available(macOS 12, *)) {
return [[VZMultipleDirectoryShare alloc] initWithDirectories:(NSDictionary<NSString *, VZSharedDirectory *> *)sharedDirectories];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize the VZVirtioFileSystemDeviceConfiguration from the fs tag.
@param tag
The tag to use for this device configuration.
@return A VZVirtioFileSystemDeviceConfiguration
*/
void *newVZVirtioFileSystemDeviceConfiguration(const char *tag, void **error)
{
if (@available(macOS 12, *)) {
NSString *tagNSString = [NSString stringWithUTF8String:tag];
BOOL valid = [VZVirtioFileSystemDeviceConfiguration validateTag:tagNSString error:(NSError *_Nullable *_Nullable)error];
if (!valid) {
return nil;
}
return [[VZVirtioFileSystemDeviceConfiguration alloc] initWithTag:tagNSString];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Sets share associated with this configuration.
*/
void setVZVirtioFileSystemDeviceConfigurationShare(void *config, void *share)
{
if (@available(macOS 12, *)) {
[(VZVirtioFileSystemDeviceConfiguration *)config setShare:(VZDirectoryShare *)share];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a new configuration for a USB pointing device that reports absolute coordinates.
@discussion This device can be used by VZVirtualMachineView to send pointer events to the virtual machine.
*/
void *newVZUSBScreenCoordinatePointingDeviceConfiguration()
{
if (@available(macOS 12, *)) {
return [[VZUSBScreenCoordinatePointingDeviceConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a new configuration for a USB keyboard.
@discussion This device can be used by VZVirtualMachineView to send key events to the virtual machine.
*/
void *newVZUSBKeyboardConfiguration()
{
if (@available(macOS 12, *)) {
return [[VZUSBKeyboardConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void sharedApplication()
{
// Create a shared app instance.
// This will initialize the global variable
// 'NSApp' with the application instance.
[VZApplication sharedApplication];
}
void startVirtualMachineWindow(void *machine, double width, double height)
{
if (@available(macOS 12, *)) {
@autoreleasepool {
AppDelegate *appDelegate = [[[AppDelegate alloc]
initWithVirtualMachine:(VZVirtualMachine *)machine
windowWidth:(CGFloat)width
windowHeight:(CGFloat)height] autorelease];
NSApp.delegate = appDelegate;
[NSApp run];
return;
}
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}

View File

@@ -0,0 +1,16 @@
//
// virtualization_12_3.h
//
// Created by codehex.
//
#pragma once
#import "virtualization_helper.h"
#import <Virtualization/Virtualization.h>
// FIXME(codehex): this is dirty hack to avoid clang-format error like below
// "Configuration file(s) do(es) not support C++: /github.com/Code-Hex/vz/.clang-format"
#define NSURLComponents NSURLComponents
void setBlockDeviceIdentifierVZVirtioBlockDeviceConfiguration(void *blockDeviceConfig, const char *identifier, void **error);

View File

@@ -0,0 +1,25 @@
//
// virtualization_12_3.m
//
// Created by codehex.
//
#import "virtualization_12_3.h"
void setBlockDeviceIdentifierVZVirtioBlockDeviceConfiguration(void *blockDeviceConfig, const char *identifier, void **error)
{
#ifdef INCLUDE_TARGET_OSX_12_3
if (@available(macOS 12.3, *)) {
NSString *identifierNSString = [NSString stringWithUTF8String:identifier];
BOOL valid = [VZVirtioBlockDeviceConfiguration
validateBlockDeviceIdentifier:identifierNSString
error:(NSError *_Nullable *_Nullable)error];
if (!valid) {
return;
}
[(VZVirtioBlockDeviceConfiguration *)blockDeviceConfig setBlockDeviceIdentifier:identifierNSString];
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}

View File

@@ -0,0 +1,76 @@
//
// virtualization_12_arm64.h
//
// Created by codehex.
//
#pragma once
#import "virtualization_helper.h"
#import <Foundation/Foundation.h>
#import <Foundation/NSNotification.h>
#import <Virtualization/Virtualization.h>
#ifdef __arm64__
@interface ProgressObserver : NSObject
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
@end
typedef struct VZMacOSRestoreImageStruct {
const char *url;
const char *buildVersion;
NSOperatingSystemVersion operatingSystemVersion;
void *mostFeaturefulSupportedConfiguration; // (VZMacOSConfigurationRequirements *)
} VZMacOSRestoreImageStruct;
typedef struct VZMacOSConfigurationRequirementsStruct {
uint64_t minimumSupportedCPUCount;
uint64_t minimumSupportedMemorySize;
void *hardwareModel; // (VZMacHardwareModel *)
} VZMacOSConfigurationRequirementsStruct;
typedef struct VZMacHardwareModelStruct {
bool supported;
nbyteslice dataRepresentation;
} VZMacHardwareModelStruct;
/* exported from cgo */
void macOSRestoreImageCompletionHandler(void *cgoHandler, void *restoreImage, void *errPtr);
void macOSInstallCompletionHandler(void *cgoHandler, void *errPtr);
void macOSInstallFractionCompletedHandler(void *cgoHandlerPtr, double completed);
/* Mac Configurations */
void *newVZMacPlatformConfiguration();
void *newVZMacAuxiliaryStorageWithCreating(const char *storagePath, void *hardwareModel, void **error);
void *newVZMacAuxiliaryStorage(const char *storagePath);
void *newVZMacPlatformConfiguration();
void setHardwareModelVZMacPlatformConfiguration(void *config, void *hardwareModel);
void storeHardwareModelDataVZMacPlatformConfiguration(void *config, const char *filePath);
void setMachineIdentifierVZMacPlatformConfiguration(void *config, void *machineIdentifier);
void storeMachineIdentifierDataVZMacPlatformConfiguration(void *config, const char *filePath);
void setAuxiliaryStorageVZMacPlatformConfiguration(void *config, void *auxiliaryStorage);
void *newVZMacOSBootLoader();
void *newVZMacGraphicsDeviceConfiguration();
void setDisplaysVZMacGraphicsDeviceConfiguration(void *graphicsConfiguration, void *displays);
void *newVZMacGraphicsDisplayConfiguration(NSInteger widthInPixels, NSInteger heightInPixels, NSInteger pixelsPerInch);
void *newVZMacHardwareModelWithPath(const char *hardwareModelPath);
void *newVZMacHardwareModelWithBytes(void *hardwareModelBytes, int len);
void *newVZMacMachineIdentifier();
void *newVZMacMachineIdentifierWithPath(const char *machineIdentifierPath);
void *newVZMacMachineIdentifierWithBytes(void *machineIdentifierBytes, int len);
nbyteslice getVZMacMachineIdentifierDataRepresentation(void *machineIdentifierPtr);
VZMacOSRestoreImageStruct convertVZMacOSRestoreImage2Struct(void *restoreImagePtr);
void fetchLatestSupportedMacOSRestoreImageWithCompletionHandler(void *cgoHandler);
void loadMacOSRestoreImageFile(const char *ipswPath, void *cgoHandler);
VZMacOSConfigurationRequirementsStruct convertVZMacOSConfigurationRequirements2Struct(void *requirementsPtr);
VZMacHardwareModelStruct convertVZMacHardwareModel2Struct(void *hardwareModelPtr);
void *newVZMacOSInstaller(void *virtualMachine, void *vmQueue, const char *restoreImageFilePath);
void *newProgressObserverVZMacOSInstaller();
void installByVZMacOSInstaller(void *installerPtr, void *vmQueue, void *progressObserverPtr, void *completionHandler, void *fractionCompletedHandler);
void cancelInstallVZMacOSInstaller(void *installerPtr);
#endif

View File

@@ -0,0 +1,459 @@
//
// virtualization_12_arm64.m
//
// Created by codehex.
//
#ifdef __arm64__
#import "virtualization_12_arm64.h"
@implementation ProgressObserver
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
{
if ([keyPath isEqualToString:@"fractionCompleted"] && [object isKindOfClass:[NSProgress class]]) {
NSProgress *progress = (NSProgress *)object;
macOSInstallFractionCompletedHandler(context, progress.fractionCompleted);
if (progress.finished) {
[progress removeObserver:self forKeyPath:@"fractionCompleted"];
}
}
}
@end
/*!
@abstract Write an initialized VZMacAuxiliaryStorage to a storagePath on a file system.
@param storagePath The storagePath to write the auxiliary storage to on the local file system.
@param hardwareModel The hardware model to use. The auxiliary storage can be laid out differently for different hardware models.
@param options Initialization options.
@param error If not nil, used to report errors if creation fails.
@return A newly initialized VZMacAuxiliaryStorage on success. If an error was encountered returns @c nil, and @c error contains the error.
*/
void *newVZMacAuxiliaryStorageWithCreating(const char *storagePath, void *hardwareModel, void **error)
{
if (@available(macOS 12, *)) {
NSString *storagePathNSString = [NSString stringWithUTF8String:storagePath];
NSURL *storageURL = [NSURL fileURLWithPath:storagePathNSString];
return [[VZMacAuxiliaryStorage alloc] initCreatingStorageAtURL:storageURL
hardwareModel:(VZMacHardwareModel *)hardwareModel
options:VZMacAuxiliaryStorageInitializationOptionAllowOverwrite
error:(NSError *_Nullable *_Nullable)error];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize the auxiliary storage from the storagePath of an existing file.
@param URL The URL of the auxiliary storage on the local file system.
@discussion To create a new auxiliary storage, use -[VZMacAuxiliaryStorage initCreatingStorageAtURL:hardwareModel:options:error].
*/
void *newVZMacAuxiliaryStorage(const char *storagePath)
{
if (@available(macOS 12, *)) {
NSString *storagePathNSString = [NSString stringWithUTF8String:storagePath];
NSURL *storageURL = [NSURL fileURLWithPath:storagePathNSString];
// Use initWithURL: in macOS 13.x
// https://developer.apple.com/documentation/virtualization/vzmacauxiliarystorage?language=objc
return [[VZMacAuxiliaryStorage alloc] initWithContentsOfURL:storageURL];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract The platform configuration for booting macOS on Apple Silicon.
@discussion
When creating a virtual machine from scratch, the hardwareModel and auxiliaryStorage depend on the restore image
that will be used to install macOS.
To choose the hardware model, start from VZMacOSRestoreImage.mostFeaturefulSupportedConfiguration to get a supported configuration, then
use its VZMacOSConfigurationRequirements.hardwareModel property to get the hardware model.
Use the hardware model to set up VZMacPlatformConfiguration and to initialize a new auxiliary storage with
-[VZMacAuxiliaryStorage initCreatingStorageAtURL:hardwareModel:options:error:].
When a virtual machine is saved to disk then loaded again, the hardwareModel, machineIdentifier and auxiliaryStorage
must be restored to their original values.
If multiple virtual machines are created from the same configuration, each should have a unique auxiliaryStorage and machineIdentifier.
@seealso VZMacOSRestoreImage
@seealso VZMacOSConfigurationRequirements
*/
void *newVZMacPlatformConfiguration()
{
if (@available(macOS 12, *)) {
return [[VZMacPlatformConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the Mac hardware model.
*/
void setHardwareModelVZMacPlatformConfiguration(void *config, void *hardwareModel)
{
if (@available(macOS 12, *)) {
[(VZMacPlatformConfiguration *)config setHardwareModel:(VZMacHardwareModel *)hardwareModel];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
// Store the hardware model to disk so that we can retrieve them for subsequent boots.
void storeHardwareModelDataVZMacPlatformConfiguration(void *config, const char *filePath)
{
if (@available(macOS 12, *)) {
VZMacPlatformConfiguration *macPlatformConfiguration = (VZMacPlatformConfiguration *)config;
NSString *filePathNSString = [NSString stringWithUTF8String:filePath];
NSURL *fileURL = [NSURL fileURLWithPath:filePathNSString];
[macPlatformConfiguration.hardwareModel.dataRepresentation writeToURL:fileURL atomically:YES];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the Mac machine identifier.
@discussion
Running two virtual machines concurrently with the same identifier results in undefined behavior in the guest operating system.
*/
void setMachineIdentifierVZMacPlatformConfiguration(void *config, void *machineIdentifier)
{
if (@available(macOS 12, *)) {
[(VZMacPlatformConfiguration *)config setMachineIdentifier:(VZMacMachineIdentifier *)machineIdentifier];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
// Store the machine identifier to disk so that we can retrieve them for subsequent boots.
void storeMachineIdentifierDataVZMacPlatformConfiguration(void *config, const char *filePath)
{
if (@available(macOS 12, *)) {
VZMacPlatformConfiguration *macPlatformConfiguration = (VZMacPlatformConfiguration *)config;
NSString *filePathNSString = [NSString stringWithUTF8String:filePath];
NSURL *fileURL = [NSURL fileURLWithPath:filePathNSString];
[macPlatformConfiguration.machineIdentifier.dataRepresentation writeToURL:fileURL atomically:YES];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the Mac auxiliary storage.
@discussion
When creating a virtual machine from scratch, the hardware model of the auxiliaryStorage must match the hardware model of
the hardwareModel property.
*/
void setAuxiliaryStorageVZMacPlatformConfiguration(void *config, void *auxiliaryStorage)
{
if (@available(macOS 12, *)) {
[(VZMacPlatformConfiguration *)config setAuxiliaryStorage:(VZMacAuxiliaryStorage *)auxiliaryStorage];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Boot loader configuration for booting macOS on Apple Silicon.
@discussion
You must use a VZMacPlatformConfiguration in conjunction with the macOS boot loader.
It is invalid to use it with any other platform configuration.
@see VZMacPlatformConfiguration
@see VZVirtualMachineConfiguration.platform.
*/
void *newVZMacOSBootLoader()
{
if (@available(macOS 12, *)) {
return [[VZMacOSBootLoader alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a new configuration for a Mac graphics device.
@discussion This device can be used to attach a display to be shown in a VZVirtualMachineView.
*/
void *newVZMacGraphicsDeviceConfiguration()
{
if (@available(macOS 12, *)) {
return [[VZMacGraphicsDeviceConfiguration alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the displays to be attached to this graphics device.
*/
void setDisplaysVZMacGraphicsDeviceConfiguration(void *graphicsConfiguration, void *displays)
{
if (@available(macOS 12, *)) {
[(VZMacGraphicsDeviceConfiguration *)graphicsConfiguration setDisplays:[(NSMutableArray *)displays copy]];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a display configuration with the specified pixel dimensions and pixel density.
@param widthInPixels The width of the display, in pixels.
@param heightInPixels The height of the display, in pixels.
@param pixelsPerInch The pixel density as a number of pixels per inch.
*/
void *newVZMacGraphicsDisplayConfiguration(NSInteger widthInPixels, NSInteger heightInPixels, NSInteger pixelsPerInch)
{
if (@available(macOS 12, *)) {
return [[VZMacGraphicsDisplayConfiguration alloc]
initWithWidthInPixels:widthInPixels
heightInPixels:heightInPixels
pixelsPerInch:pixelsPerInch];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Get the hardware model described by the specified data representation.
@param dataRepresentation The opaque data representation of the hardware model to be obtained.
*/
void *newVZMacHardwareModelWithPath(const char *hardwareModelPath)
{
if (@available(macOS 12, *)) {
VZMacHardwareModel *hardwareModel;
NSString *hardwareModelPathNSString = [NSString stringWithUTF8String:hardwareModelPath];
NSURL *hardwareModelPathURL = [NSURL fileURLWithPath:hardwareModelPathNSString];
@autoreleasepool {
NSData *hardwareModelData = [[NSData alloc] initWithContentsOfURL:hardwareModelPathURL];
hardwareModel = [[VZMacHardwareModel alloc] initWithDataRepresentation:hardwareModelData];
}
return hardwareModel;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void *newVZMacHardwareModelWithBytes(void *hardwareModelBytes, int len)
{
if (@available(macOS 12, *)) {
VZMacHardwareModel *hardwareModel;
@autoreleasepool {
NSData *hardwareModelData = [[NSData alloc] initWithBytes:hardwareModelBytes length:(NSUInteger)len];
hardwareModel = [[VZMacHardwareModel alloc] initWithDataRepresentation:hardwareModelData];
}
return hardwareModel;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a new unique machine identifier.
*/
void *newVZMacMachineIdentifier()
{
if (@available(macOS 12, *)) {
return [[VZMacMachineIdentifier alloc] init];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Get the machine identifier described by the specified data representation.
@param dataRepresentation The opaque data representation of the machine identifier to be obtained.
@return A unique identifier identical to the one that generated the dataRepresentation, or nil if the data is invalid.
@see VZMacMachineIdentifier.dataRepresentation
*/
void *newVZMacMachineIdentifierWithPath(const char *machineIdentifierPath)
{
if (@available(macOS 12, *)) {
VZMacMachineIdentifier *machineIdentifier;
NSString *machineIdentifierPathNSString = [NSString stringWithUTF8String:machineIdentifierPath];
NSURL *machineIdentifierPathURL = [NSURL fileURLWithPath:machineIdentifierPathNSString];
@autoreleasepool {
NSData *machineIdentifierData = [[NSData alloc] initWithContentsOfURL:machineIdentifierPathURL];
machineIdentifier = [[VZMacMachineIdentifier alloc] initWithDataRepresentation:machineIdentifierData];
}
return machineIdentifier;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void *newVZMacMachineIdentifierWithBytes(void *machineIdentifierBytes, int len)
{
if (@available(macOS 12, *)) {
VZMacMachineIdentifier *machineIdentifier;
@autoreleasepool {
NSData *machineIdentifierData = [[NSData alloc] initWithBytes:machineIdentifierBytes length:(NSUInteger)len];
machineIdentifier = [[VZMacMachineIdentifier alloc] initWithDataRepresentation:machineIdentifierData];
}
return machineIdentifier;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
nbyteslice getVZMacMachineIdentifierDataRepresentation(void *machineIdentifierPtr)
{
if (@available(macOS 12, *)) {
VZMacMachineIdentifier *machineIdentifier = (VZMacMachineIdentifier *)machineIdentifierPtr;
NSData *data = [machineIdentifier dataRepresentation];
nbyteslice ret = {
.ptr = (void *)[data bytes],
.len = (int)[data length],
};
return ret;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
VZMacOSRestoreImageStruct convertVZMacOSRestoreImage2Struct(void *restoreImagePtr)
{
if (@available(macOS 12, *)) {
VZMacOSRestoreImage *restoreImage = (VZMacOSRestoreImage *)restoreImagePtr;
VZMacOSRestoreImageStruct ret;
ret.url = [[[restoreImage URL] absoluteString] UTF8String];
ret.buildVersion = [[restoreImage buildVersion] UTF8String];
ret.operatingSystemVersion = [restoreImage operatingSystemVersion];
// maybe unnecessary CFBridgingRetain. if use CFBridgingRetain, should use CFRelease.
ret.mostFeaturefulSupportedConfiguration = (void *)CFBridgingRetain([restoreImage mostFeaturefulSupportedConfiguration]);
return ret;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void fetchLatestSupportedMacOSRestoreImageWithCompletionHandler(void *cgoHandler)
{
if (@available(macOS 12, *)) {
[VZMacOSRestoreImage fetchLatestSupportedWithCompletionHandler:^(VZMacOSRestoreImage *restoreImage, NSError *error) {
VZMacOSRestoreImageStruct restoreImageStruct = convertVZMacOSRestoreImage2Struct(restoreImage);
macOSRestoreImageCompletionHandler(cgoHandler, &restoreImageStruct, error);
}];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void loadMacOSRestoreImageFile(const char *ipswPath, void *cgoHandler)
{
if (@available(macOS 12, *)) {
NSString *ipswPathNSString = [NSString stringWithUTF8String:ipswPath];
NSURL *ipswURL = [NSURL fileURLWithPath:ipswPathNSString];
[VZMacOSRestoreImage loadFileURL:ipswURL
completionHandler:^(VZMacOSRestoreImage *restoreImage, NSError *error) {
VZMacOSRestoreImageStruct restoreImageStruct = convertVZMacOSRestoreImage2Struct(restoreImage);
macOSRestoreImageCompletionHandler(cgoHandler, &restoreImageStruct, error);
}];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
VZMacOSConfigurationRequirementsStruct convertVZMacOSConfigurationRequirements2Struct(void *requirementsPtr)
{
if (@available(macOS 12, *)) {
VZMacOSConfigurationRequirements *requirements = (VZMacOSConfigurationRequirements *)requirementsPtr;
VZMacOSConfigurationRequirementsStruct ret;
ret.minimumSupportedCPUCount = (uint64_t)[requirements minimumSupportedCPUCount];
ret.minimumSupportedMemorySize = (uint64_t)[requirements minimumSupportedMemorySize];
// maybe unnecessary CFBridgingRetain. if use CFBridgingRetain, should use CFRelease.
ret.hardwareModel = (void *)CFBridgingRetain([requirements hardwareModel]);
return ret;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
VZMacHardwareModelStruct convertVZMacHardwareModel2Struct(void *hardwareModelPtr)
{
if (@available(macOS 12, *)) {
VZMacHardwareModel *hardwareModel = (VZMacHardwareModel *)hardwareModelPtr;
VZMacHardwareModelStruct ret;
ret.supported = (bool)[hardwareModel isSupported];
NSData *data = [hardwareModel dataRepresentation];
nbyteslice retByteSlice = {
.ptr = (void *)[data bytes],
.len = (int)[data length],
};
ret.dataRepresentation = retByteSlice;
return ret;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a VZMacOSInstaller object.
@param virtualMachine The virtual machine that the operating system will be installed onto.
@param restoreImageFileURL A file URL indicating the macOS restore image to install.
@discussion
The virtual machine platform must be macOS and the restore image URL must be a file URL referring to a file on disk or an exception will be raised.
This method must be called on the virtual machine's queue.
*/
void *newVZMacOSInstaller(void *virtualMachine, void *vmQueue, const char *restoreImageFilePath)
{
if (@available(macOS 12, *)) {
__block VZMacOSInstaller *ret;
NSString *restoreImageFilePathNSString = [NSString stringWithUTF8String:restoreImageFilePath];
NSURL *restoreImageFileURL = [NSURL fileURLWithPath:restoreImageFilePathNSString];
dispatch_sync((dispatch_queue_t)vmQueue, ^{
ret = [[VZMacOSInstaller alloc] initWithVirtualMachine:(VZVirtualMachine *)virtualMachine restoreImageURL:restoreImageFileURL];
});
return ret;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void *newProgressObserverVZMacOSInstaller()
{
return [[ProgressObserver alloc] init];
}
void installByVZMacOSInstaller(void *installerPtr, void *vmQueue, void *progressObserverPtr, void *completionHandler, void *fractionCompletedHandler)
{
if (@available(macOS 12, *)) {
VZMacOSInstaller *installer = (VZMacOSInstaller *)installerPtr;
dispatch_sync((dispatch_queue_t)vmQueue, ^{
[installer installWithCompletionHandler:^(NSError *error) {
macOSInstallCompletionHandler(completionHandler, error);
}];
[installer.progress
addObserver:(ProgressObserver *)progressObserverPtr
forKeyPath:@"fractionCompleted"
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:fractionCompletedHandler];
});
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void cancelInstallVZMacOSInstaller(void *installerPtr)
{
if (@available(macOS 12, *)) {
VZMacOSInstaller *installer = (VZMacOSInstaller *)installerPtr;
if (installer.progress.cancellable) {
[installer.progress cancel];
}
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
#endif

View File

@@ -0,0 +1,48 @@
//
// virtualization_13.h
//
// Created by codehex.
//
#pragma once
#import "virtualization_helper.h"
#import <Virtualization/Virtualization.h>
/* macOS 13 API */
void setConsoleDevicesVZVirtualMachineConfiguration(void *config, void *consoleDevices);
void *newVZEFIBootLoader();
void setVariableStoreVZEFIBootLoader(void *bootLoaderPtr, void *variableStore);
void *newVZEFIVariableStorePath(const char *variableStorePath);
void *newCreatingVZEFIVariableStoreAtPath(const char *variableStorePath, void **error);
void *newVZGenericMachineIdentifierWithBytes(void *machineIdentifierBytes, int len);
nbyteslice getVZGenericMachineIdentifierDataRepresentation(void *machineIdentifierPtr);
void *newVZGenericMachineIdentifier();
void setMachineIdentifierVZGenericPlatformConfiguration(void *config, void *machineIdentifier);
void *newVZUSBMassStorageDeviceConfiguration(void *attachment);
void *newVZVirtioGraphicsDeviceConfiguration();
void setScanoutsVZVirtioGraphicsDeviceConfiguration(void *graphicsConfiguration, void *scanouts);
void *newVZVirtioGraphicsScanoutConfiguration(NSInteger widthInPixels, NSInteger heightInPixels);
void *newVZVirtioConsoleDeviceConfiguration();
void *portsVZVirtioConsoleDeviceConfiguration(void *consoleDevice);
uint32_t maximumPortCountVZVirtioConsolePortConfigurationArray(void *ports);
void *getObjectAtIndexedSubscriptVZVirtioConsolePortConfigurationArray(void *portsPtr, int portIndex);
void setObjectAtIndexedSubscriptVZVirtioConsolePortConfigurationArray(void *portsPtr, void *portConfig, int portIndex);
void *newVZVirtioConsolePortConfiguration();
void setNameVZVirtioConsolePortConfiguration(void *consolePortConfig, const char *name);
void setIsConsoleVZVirtioConsolePortConfiguration(void *consolePortConfig, bool isConsole);
void setAttachmentVZVirtioConsolePortConfiguration(void *consolePortConfig, void *serialPortAttachment);
void *newVZSpiceAgentPortAttachment();
void setSharesClipboardVZSpiceAgentPortAttachment(void *attachment, bool sharesClipboard);
const char *getSpiceAgentPortName();
void startWithOptionsCompletionHandler(void *machine, void *queue, void *options, void *completionHandler);
const char *getMacOSGuestAutomountTag();
void setMaximumTransmissionUnitVZFileHandleNetworkDeviceAttachment(void *attachment, NSInteger mtu);

View File

@@ -0,0 +1,478 @@
//
// virtualization_13.m
//
// Created by codehex.
//
#import "virtualization_13.h"
#import "virtualization_view.h"
/*!
@abstract List of console devices. Empty by default.
@see VZVirtioConsoleDeviceConfiguration
*/
void setConsoleDevicesVZVirtualMachineConfiguration(void *config, void *consoleDevices)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
[(VZVirtualMachineConfiguration *)config
setConsoleDevices:[(NSMutableArray *)consoleDevices copy]];
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Boot loader configuration for booting guest operating systems expecting an EFI ROM.
@discussion
You must use a VZGenericPlatformConfiguration in conjunction with the EFI boot loader.
It is invalid to use it with any other platform configuration.
@see VZGenericPlatformConfiguration
@see VZVirtualMachineConfiguration.platform.
*/
void *newVZEFIBootLoader()
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZEFIBootLoader alloc] init];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the EFI variable store.
*/
void setVariableStoreVZEFIBootLoader(void *bootLoaderPtr, void *variableStore)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
[(VZEFIBootLoader *)bootLoaderPtr setVariableStore:(VZEFIVariableStore *)variableStore];
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize the variable store from the path of an existing file.
@param variableStorePath The path of the variable store on the local file system.
@discussion To create a new variable store, use -[VZEFIVariableStore initCreatingVariableStoreAtURL:options:error].
*/
void *newVZEFIVariableStorePath(const char *variableStorePath)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
NSString *variableStorePathNSString = [NSString stringWithUTF8String:variableStorePath];
NSURL *variableStoreURL = [NSURL fileURLWithPath:variableStorePathNSString];
return [[VZEFIVariableStore alloc] initWithURL:variableStoreURL];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Write an initialized VZEFIVariableStore to path on a file system.
@param variableStorePath The path to write the variable store to on the local file system.
@param error If not nil, used to report errors if creation fails.
@return A newly initialized VZEFIVariableStore on success. If an error was encountered returns @c nil, and @c error contains the error.
*/
void *newCreatingVZEFIVariableStoreAtPath(const char *variableStorePath, void **error)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
NSString *variableStorePathNSString = [NSString stringWithUTF8String:variableStorePath];
NSURL *variableStoreURL = [NSURL fileURLWithPath:variableStorePathNSString];
return [[VZEFIVariableStore alloc]
initCreatingVariableStoreAtURL:variableStoreURL
options:VZEFIVariableStoreInitializationOptionAllowOverwrite
error:(NSError *_Nullable *_Nullable)error];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Get the machine identifier described by the specified data representation.
@param dataRepresentation The opaque data representation of the machine identifier to be obtained.
@return A unique identifier identical to the one that generated the dataRepresentation, or nil if the data is invalid.
@see VZGenericMachineIdentifier.dataRepresentation
*/
void *newVZGenericMachineIdentifierWithBytes(void *machineIdentifierBytes, int len)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
VZGenericMachineIdentifier *machineIdentifier;
@autoreleasepool {
NSData *machineIdentifierData = [[NSData alloc] initWithBytes:machineIdentifierBytes length:(NSUInteger)len];
machineIdentifier = [[VZGenericMachineIdentifier alloc] initWithDataRepresentation:machineIdentifierData];
}
return machineIdentifier;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Opaque data representation of the machine identifier.
@discussion This can be used to recreate the same machine identifier with -[VZGenericMachineIdentifier initWithDataRepresentation:].
@see -[VZGenericMachineIdentifier initWithDataRepresentation:]
*/
nbyteslice getVZGenericMachineIdentifierDataRepresentation(void *machineIdentifierPtr)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
VZGenericMachineIdentifier *machineIdentifier = (VZGenericMachineIdentifier *)machineIdentifierPtr;
NSData *data = [machineIdentifier dataRepresentation];
nbyteslice ret = {
.ptr = (void *)[data bytes],
.len = (int)[data length],
};
return ret;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a new unique machine identifier.
*/
void *newVZGenericMachineIdentifier()
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZGenericMachineIdentifier alloc] init];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the machine identifier.
*/
void setMachineIdentifierVZGenericPlatformConfiguration(void *config, void *machineIdentifier)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
[(VZGenericPlatformConfiguration *)config setMachineIdentifier:(VZGenericMachineIdentifier *)machineIdentifier];
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Initialize a VZUSBMassStorageDeviceConfiguration with a device attachment.
@param attachment The storage device attachment. This defines how the virtualized device operates on the host side.
@see VZDiskImageStorageDeviceAttachment
*/
void *newVZUSBMassStorageDeviceConfiguration(void *attachment)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZUSBMassStorageDeviceConfiguration alloc]
initWithAttachment:(VZStorageDeviceAttachment *)attachment];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Creates a new Configuration for a Virtio graphics device.
@discussion
This device configuration creates a graphics device using paravirtualization.
The emulated device follows the Virtio GPU Device specification.
This device can be used to attach a display to be shown in a VZVirtualMachineView.
*/
void *newVZVirtioGraphicsDeviceConfiguration()
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZVirtioGraphicsDeviceConfiguration alloc] init];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the scanouts to be attached to this graphics device.
@discussion
Maximum of one scanout is supported.
*/
void setScanoutsVZVirtioGraphicsDeviceConfiguration(void *graphicsConfiguration, void *scanouts)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
[(VZVirtioGraphicsDeviceConfiguration *)graphicsConfiguration
setScanouts:[(NSMutableArray *)scanouts copy]];
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a scanout configuration with the specified pixel dimensions.
@param widthInPixels The width of the scanout, in pixels.
@param heightInPixels The height of the scanout, in pixels.
*/
void *newVZVirtioGraphicsScanoutConfiguration(NSInteger widthInPixels, NSInteger heightInPixels)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZVirtioGraphicsScanoutConfiguration alloc]
initWithWidthInPixels:widthInPixels
heightInPixels:heightInPixels];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Create a new Virtio Console Device
@discussion
This console device enables communication between the host and the guest using console ports through the Virtio interface.
The device sets up one or more ports via VZVirtioConsolePortConfiguration on the Virtio console device.
@see VZVirtioConsolePortConfiguration
@see VZVirtualMachineConfiguration.consoleDevices
*/
void *newVZVirtioConsoleDeviceConfiguration()
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZVirtioConsoleDeviceConfiguration alloc] init];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract The console ports to be configured for this console device.
*/
void *portsVZVirtioConsoleDeviceConfiguration(void *consoleDevice)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [(VZVirtioConsoleDeviceConfiguration *)consoleDevice ports]; // VZVirtioConsolePortConfigurationArray
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract The maximum number of ports allocated by this device. The default is the number of ports attached to this device.
*/
uint32_t maximumPortCountVZVirtioConsolePortConfigurationArray(void *ports)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [(VZVirtioConsolePortConfigurationArray *)ports maximumPortCount];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Get a port configuration at the specified index.
*/
void *getObjectAtIndexedSubscriptVZVirtioConsolePortConfigurationArray(void *portsPtr, int portIndex)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
VZVirtioConsolePortConfigurationArray *ports = (VZVirtioConsolePortConfigurationArray *)portsPtr;
return ports[portIndex];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set a port configuration at the specified index.
*/
void setObjectAtIndexedSubscriptVZVirtioConsolePortConfigurationArray(void *portsPtr, void *portConfig, int portIndex)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
VZVirtioConsolePortConfigurationArray *ports = (VZVirtioConsolePortConfigurationArray *)portsPtr;
ports[portIndex] = (VZVirtioConsolePortConfiguration *)portConfig;
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Virtio Console Port
@discussion
A console port is a two-way communication channel between a host VZSerialPortAttachment and a virtual machine console port. One or more console ports are attached to a Virtio console device.
An optional name may be set for a console port. A console port may also be configured for use as the system console.
@see VZConsolePortConfiguration
@see VZVirtualMachineConfiguration.consoleDevices
*/
void *newVZVirtioConsolePortConfiguration()
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZVirtioConsolePortConfiguration alloc] init];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the console port's name. The default behavior is to not use a name unless set.
*/
void setNameVZVirtioConsolePortConfiguration(void *consolePortConfig, const char *name)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
NSString *nameNSString = [NSString stringWithUTF8String:name];
[(VZVirtioConsolePortConfiguration *)consolePortConfig setName:nameNSString];
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the console port may be marked for use as the system console. The default is false.
*/
void setIsConsoleVZVirtioConsolePortConfiguration(void *consolePortConfig, bool isConsole)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
[(VZVirtioConsolePortConfiguration *)consolePortConfig setIsConsole:(BOOL)isConsole];
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Set the console port attachment. Defines how the virtual machine's console port interfaces with the host system. Default is nil.
@see VZFileHandleSerialPortAttachment
@see VZFileSerialPortAttachment
@see VZSpiceAgentPortAttachment
*/
void setAttachmentVZVirtioConsolePortConfiguration(void *consolePortConfig, void *serialPortAttachment)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
[(VZVirtioConsolePortConfiguration *)consolePortConfig
setAttachment:(VZSerialPortAttachment *)serialPortAttachment];
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
void *newVZSpiceAgentPortAttachment()
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZSpiceAgentPortAttachment alloc] init];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Enable the Spice agent clipboard sharing capability.
@discussion
If enabled, the clipboard capability will be advertised to the Spice guest agent. Copy and paste events
will be shared between the host and the virtual machine.
This property is enabled by default.
*/
void setSharesClipboardVZSpiceAgentPortAttachment(void *attachment, bool sharesClipboard)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [(VZSpiceAgentPortAttachment *)attachment setSharesClipboard:(BOOL)sharesClipboard];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract The Spice agent port name.
@discussion
A console port configured with this name will spawn a Spice guest agent if supported by the guest.
VZConsolePortConfiguration.attachment must be set to VZSpiceAgentPortAttachment.
VZVirtioConsolePortConfiguration.isConsole must remain false on a Spice agent port.
*/
const char *getSpiceAgentPortName()
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZSpiceAgentPortAttachment spiceAgentPortName] UTF8String];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Start a virtual machine with options.
@discussion
Start a virtual machine that is in either Stopped or Error state.
@param options Options used to control how the virtual machine is started.
@param completionHandler Block called after the virtual machine has been successfully started or on error.
The error parameter passed to the block is nil if the start was successful.
@seealso VZMacOSVirtualMachineStartOptions
*/
void startWithOptionsCompletionHandler(void *machine, void *queue, void *options, void *completionHandler)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
vm_completion_handler_t handler = makeVMCompletionHandler(completionHandler);
dispatch_sync((dispatch_queue_t)queue, ^{
[(VZVirtualMachine *)machine startWithOptions:options completionHandler:handler];
});
Block_release(handler);
return;
}
#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();
}
/*!
@abstract The maximum transmission unit (MTU) associated with this attachment.
@discussion
The client side of the associated datagram socket must be properly configured with the appropriate values for
`SO_SNDBUF`, and `SO_RCVBUF`, which can be set using the `setsockopt` system call. The value of `SO_RCVBUF` is
expected to be at least double the value of `SO_SNDBUF`, and for optimal performance, the value of `SO_RCVBUF`
is recommended to be four times the value of `SO_SNDBUF`.
The default MTU is 1500.
The maximum MTU allowed is 65535, and the minimum MTU allowed is 1500. An invalid MTU value will result in an invalid
virtual machine configuration.
*/
void setMaximumTransmissionUnitVZFileHandleNetworkDeviceAttachment(void *attachment, NSInteger mtu)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
[(VZFileHandleNetworkDeviceAttachment *)attachment setMaximumTransmissionUnit:mtu];
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}

View File

@@ -0,0 +1,29 @@
//
// virtualization_13_arm64.h
//
// Created by codehex.
//
#pragma once
#ifdef __arm64__
// FIXME(codehex): this is dirty hack to avoid clang-format error like below
// "Configuration file(s) do(es) not support C++: /github.com/Code-Hex/vz/.clang-format"
#define NSURLComponents NSURLComponents
#import "virtualization_helper.h"
#import <Virtualization/Virtualization.h>
/* exported from cgo */
void linuxInstallRosettaWithCompletionHandler(void *cgoHandler, void *errPtr);
void *newVZLinuxRosettaDirectoryShare(void **error);
void linuxInstallRosetta(void *cgoHandler);
int availabilityVZLinuxRosettaDirectoryShare();
void *newVZMacOSVirtualMachineStartOptions(bool startUpFromMacOSRecovery);
void *newVZMacTrackpadConfiguration();
#endif

View File

@@ -0,0 +1,89 @@
//
// virtualization_13_arm64.m
//
// Created by codehex.
//
#import "virtualization_13_arm64.h"
/*!
@abstract Initialize a Rosetta directory share if Rosetta support for Linux binaries is installed.
@param error Error object to store the error, if an error exists.
@discussion The call returns an error if Rosetta is not available for a directory share. To install Rosetta support, use +[VZLinuxRosettaDirectoryShare installRosettaWithCompletionHandler:].
*/
void *newVZLinuxRosettaDirectoryShare(void **error)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return [[VZLinuxRosettaDirectoryShare alloc] initWithError:(NSError *_Nullable *_Nullable)error];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Download and install Rosetta support for Linux binaries if necessary.
@param completionHandler The completion handler gets called with a valid error on failure and a nil error on success. It will also be invoked on an arbitrary queue.
@discussion
The call prompts the user through the download and install flow for Rosetta. This call is successful if the error is nil.
@see +[VZLinuxRosettaDirectoryShare availability]
*/
void linuxInstallRosetta(void *cgoHandler)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
[VZLinuxRosettaDirectoryShare installRosettaWithCompletionHandler:^(NSError *error) {
linuxInstallRosettaWithCompletionHandler(cgoHandler, error);
}];
return;
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Check the availability of Rosetta support for the directory share.
*/
int availabilityVZLinuxRosettaDirectoryShare()
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
return (int)[VZLinuxRosettaDirectoryShare availability];
}
#endif
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract Options controlling startup behavior of a virtual machine using VZMacOSBootLoader.
*/
void *newVZMacOSVirtualMachineStartOptions(bool startUpFromMacOSRecovery)
{
#ifdef INCLUDE_TARGET_OSX_13
if (@available(macOS 13, *)) {
VZMacOSVirtualMachineStartOptions *opts = [[VZMacOSVirtualMachineStartOptions alloc] init];
[opts setStartUpFromMacOSRecovery:(BOOL)startUpFromMacOSRecovery];
return opts;
}
#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();
}

View File

@@ -0,0 +1,578 @@
//go:build darwin && arm64
// +build darwin,arm64
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_arm64.h"
# include "virtualization_13_arm64.h"
*/
import "C"
import (
"context"
"fmt"
"io"
"net/http"
"os"
"runtime/cgo"
"sync"
"sync/atomic"
"unsafe"
"github.com/Code-Hex/vz/v3/internal/objc"
"github.com/Code-Hex/vz/v3/internal/progress"
)
// WithStartUpFromMacOSRecovery is an option to specifiy whether to start up
// from macOS Recovery for macOS VM.
//
// This is only supported on macOS 13 and newer, error will
// be returned on older versions.
func WithStartUpFromMacOSRecovery(startInRecovery bool) VirtualMachineStartOption {
return func(vmso *virtualMachineStartOptions) error {
if err := macOSAvailable(13); err != nil {
return err
}
vmso.macOSVirtualMachineStartOptionsPtr = C.newVZMacOSVirtualMachineStartOptions(
C.bool(startInRecovery),
)
return nil
}
}
// MacHardwareModel describes a specific virtual Mac hardware model.
type MacHardwareModel struct {
*pointer
supported bool
dataRepresentation []byte
}
// NewMacHardwareModelWithDataPath initialize a new hardware model described by the specified pathname.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacHardwareModelWithDataPath(pathname string) (*MacHardwareModel, error) {
b, err := os.ReadFile(pathname)
if err != nil {
return nil, err
}
return NewMacHardwareModelWithData(b)
}
// NewMacHardwareModelWithData initialize a new hardware model described by the specified data representation.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacHardwareModelWithData(b []byte) (*MacHardwareModel, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
ptr := C.newVZMacHardwareModelWithBytes(
unsafe.Pointer(&b[0]),
C.int(len(b)),
)
ret := newMacHardwareModel(ptr)
objc.SetFinalizer(ret, func(self *MacHardwareModel) {
objc.Release(self)
})
return ret, nil
}
func newMacHardwareModel(ptr unsafe.Pointer) *MacHardwareModel {
ret := C.convertVZMacHardwareModel2Struct(ptr)
dataRepresentation := ret.dataRepresentation
bytePointer := (*byte)(unsafe.Pointer(dataRepresentation.ptr))
return &MacHardwareModel{
pointer: objc.NewPointer(ptr),
supported: bool(ret.supported),
// https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices
dataRepresentation: unsafe.Slice(bytePointer, dataRepresentation.len),
}
}
// Supported indicate whether this hardware model is supported by the host.
func (m *MacHardwareModel) Supported() bool { return m.supported }
// DataRepresentation opaque data representation of the hardware model.
// This can be used to recreate the same hardware model with NewMacHardwareModelWithData function.
func (m *MacHardwareModel) DataRepresentation() []byte { return m.dataRepresentation }
// MacMachineIdentifier an identifier to make a virtual machine unique.
type MacMachineIdentifier struct {
*pointer
dataRepresentation []byte
}
// NewMacMachineIdentifierWithDataPath initialize a new machine identifier described by the specified pathname.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacMachineIdentifierWithDataPath(pathname string) (*MacMachineIdentifier, error) {
b, err := os.ReadFile(pathname)
if err != nil {
return nil, err
}
return NewMacMachineIdentifierWithData(b)
}
// NewMacMachineIdentifierWithData initialize a new machine identifier described by the specified data representation.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacMachineIdentifierWithData(b []byte) (*MacMachineIdentifier, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
ptr := C.newVZMacMachineIdentifierWithBytes(
unsafe.Pointer(&b[0]),
C.int(len(b)),
)
return newMacMachineIdentifier(ptr), nil
}
// NewMacMachineIdentifier initialize a new Mac machine identifier is used by macOS guests to uniquely
// identify the virtual hardware.
//
// Two virtual machines running concurrently should not use the same identifier.
//
// If the virtual machine is serialized to disk, the identifier can be preserved in a binary representation through
// DataRepresentation method.
// The identifier can then be recreated with NewMacMachineIdentifierWithData function from the binary representation.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacMachineIdentifier() (*MacMachineIdentifier, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
return newMacMachineIdentifier(C.newVZMacMachineIdentifier()), nil
}
func newMacMachineIdentifier(ptr unsafe.Pointer) *MacMachineIdentifier {
dataRepresentation := C.getVZMacMachineIdentifierDataRepresentation(ptr)
bytePointer := (*byte)(unsafe.Pointer(dataRepresentation.ptr))
return &MacMachineIdentifier{
pointer: objc.NewPointer(ptr),
// https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices
dataRepresentation: unsafe.Slice(bytePointer, dataRepresentation.len),
}
}
// DataRepresentation opaque data representation of the machine identifier.
// This can be used to recreate the same machine identifier with NewMacMachineIdentifierWithData function.
func (m *MacMachineIdentifier) DataRepresentation() []byte { return m.dataRepresentation }
// MacAuxiliaryStorage is a struct that contains information the boot loader
// needs for booting macOS as a guest operating system.
type MacAuxiliaryStorage struct {
*pointer
storagePath string
}
// NewMacAuxiliaryStorageOption is an option type to initialize a new Mac auxiliary storage
type NewMacAuxiliaryStorageOption func(*MacAuxiliaryStorage) error
// WithCreatingMacAuxiliaryStorage is an option when initialize a new Mac auxiliary storage with data creation
// to you specified storage path.
func WithCreatingMacAuxiliaryStorage(hardwareModel *MacHardwareModel) NewMacAuxiliaryStorageOption {
return func(mas *MacAuxiliaryStorage) error {
cpath := charWithGoString(mas.storagePath)
defer cpath.Free()
nserrPtr := newNSErrorAsNil()
mas.pointer = objc.NewPointer(
C.newVZMacAuxiliaryStorageWithCreating(
cpath.CString(),
objc.Ptr(hardwareModel),
&nserrPtr,
),
)
if err := newNSError(nserrPtr); err != nil {
return err
}
return nil
}
}
// NewMacAuxiliaryStorage creates a new MacAuxiliaryStorage is based Mac auxiliary storage data from the storagePath
// of an existing file by default.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacAuxiliaryStorage(storagePath string, opts ...NewMacAuxiliaryStorageOption) (*MacAuxiliaryStorage, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
storage := &MacAuxiliaryStorage{storagePath: storagePath}
for _, opt := range opts {
if err := opt(storage); err != nil {
return nil, err
}
}
if objc.Ptr(storage) == nil {
cpath := charWithGoString(storagePath)
defer cpath.Free()
storage.pointer = objc.NewPointer(
C.newVZMacAuxiliaryStorage(cpath.CString()),
)
}
return storage, nil
}
// MacOSRestoreImage is a struct that describes a version of macOS to install on to a virtual machine.
type MacOSRestoreImage struct {
url string
buildVersion string
operatingSystemVersion OperatingSystemVersion
mostFeaturefulSupportedConfigurationPtr unsafe.Pointer
}
// URL returns URL of this restore image.
// the value of this property will be a file URL. (https://~)
// the value of this property will be a network URL referring to an installation media file. (file:///~)
func (m *MacOSRestoreImage) URL() string {
return m.url
}
// BuildVersion returns the build version this restore image contains.
func (m *MacOSRestoreImage) BuildVersion() string {
return m.buildVersion
}
// OperatingSystemVersion represents the operating system version this restore image contains.
type OperatingSystemVersion struct {
MajorVersion int64
MinorVersion int64
PatchVersion int64
}
// String returns string for the build version this restore image contains.
func (osv OperatingSystemVersion) String() string {
return fmt.Sprintf("%d.%d.%d", osv.MajorVersion, osv.MinorVersion, osv.PatchVersion)
}
// OperatingSystemVersion returns the operating system version this restore image contains.
func (m *MacOSRestoreImage) OperatingSystemVersion() OperatingSystemVersion {
return m.operatingSystemVersion
}
// MostFeaturefulSupportedConfiguration returns the configuration requirements for the most featureful
// configuration supported by the current host and by this restore image.
//
// A MacOSRestoreImage can contain installation media for multiple Mac hardware models (MacHardwareModel). Some of these
// hardware models may not be supported by the current host. This method can be used to determine the hardware model and
// configuration requirements that will provide the most complete feature set on the current host.
// If none of the hardware models are supported on the current host, this property is nil.
func (m *MacOSRestoreImage) MostFeaturefulSupportedConfiguration() *MacOSConfigurationRequirements {
return newMacOSConfigurationRequirements(m.mostFeaturefulSupportedConfigurationPtr)
}
// MacOSConfigurationRequirements describes the parameter constraints required by a specific configuration of macOS.
//
// When a VZMacOSRestoreImage is loaded, it can be inspected to determine the configurations supported by that restore image.
type MacOSConfigurationRequirements struct {
minimumSupportedCPUCount uint64
minimumSupportedMemorySize uint64
hardwareModelPtr unsafe.Pointer
}
func newMacOSConfigurationRequirements(ptr unsafe.Pointer) *MacOSConfigurationRequirements {
ret := C.convertVZMacOSConfigurationRequirements2Struct(ptr)
return &MacOSConfigurationRequirements{
minimumSupportedCPUCount: uint64(ret.minimumSupportedCPUCount),
minimumSupportedMemorySize: uint64(ret.minimumSupportedMemorySize),
hardwareModelPtr: ret.hardwareModel,
}
}
// HardwareModel returns the hardware model for this configuration.
//
// The hardware model can be used to configure a new virtual machine that meets the requirements.
// Use VZMacPlatformConfiguration.hardwareModel to configure the Mac platform, and
// Use `WithCreatingStorage` functional option of the `NewMacAuxiliaryStorage` to create its auxiliary storage.
func (m *MacOSConfigurationRequirements) HardwareModel() *MacHardwareModel {
return newMacHardwareModel(m.hardwareModelPtr)
}
// MinimumSupportedCPUCount returns the minimum supported number of CPUs for this configuration.
func (m *MacOSConfigurationRequirements) MinimumSupportedCPUCount() uint64 {
return m.minimumSupportedCPUCount
}
// MinimumSupportedMemorySize returns the minimum supported memory size for this configuration.
func (m *MacOSConfigurationRequirements) MinimumSupportedMemorySize() uint64 {
return m.minimumSupportedMemorySize
}
type macOSRestoreImageHandler func(restoreImage *MacOSRestoreImage, err error)
//export macOSRestoreImageCompletionHandler
func macOSRestoreImageCompletionHandler(cgoHandlerPtr, restoreImagePtr, errPtr unsafe.Pointer) {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
handler := cgoHandler.Value().(macOSRestoreImageHandler)
defer cgoHandler.Delete()
restoreImageStruct := (*C.VZMacOSRestoreImageStruct)(restoreImagePtr)
restoreImage := &MacOSRestoreImage{
url: (*char)(restoreImageStruct.url).String(),
buildVersion: (*char)(restoreImageStruct.buildVersion).String(),
operatingSystemVersion: OperatingSystemVersion{
MajorVersion: int64(restoreImageStruct.operatingSystemVersion.majorVersion),
MinorVersion: int64(restoreImageStruct.operatingSystemVersion.minorVersion),
PatchVersion: int64(restoreImageStruct.operatingSystemVersion.patchVersion),
},
mostFeaturefulSupportedConfigurationPtr: restoreImageStruct.mostFeaturefulSupportedConfiguration,
}
if err := newNSError(errPtr); err != nil {
handler(restoreImage, err)
} else {
handler(restoreImage, nil)
}
}
// downloadRestoreImage resumable downloads macOS restore image (ipsw) file.
func downloadRestoreImage(ctx context.Context, url string, destPath string) (*progress.Reader, error) {
// open or create
f, err := os.OpenFile(destPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
return nil, err
}
fileInfo, err := f.Stat()
if err != nil {
f.Close()
return nil, err
}
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
f.Close()
return nil, err
}
req.Header.Add("User-Agent", "github.com/Code-Hex/vz")
req.Header.Add("Range", fmt.Sprintf("bytes=%d-", fileInfo.Size()))
resp, err := http.DefaultClient.Do(req)
if err != nil {
f.Close()
return nil, err
}
if 200 > resp.StatusCode || resp.StatusCode >= 300 {
f.Close()
resp.Body.Close()
return nil, fmt.Errorf("unexpected http status code: %d", resp.StatusCode)
}
reader := progress.NewReader(resp.Body, resp.ContentLength, fileInfo.Size())
go func() {
defer f.Close()
defer resp.Body.Close()
_, err := io.Copy(f, reader)
reader.Finish(err)
}()
return reader, nil
}
// FetchLatestSupportedMacOSRestoreImage fetches the latest macOS restore image supported by this host from the network.
//
// After downloading the restore image, you can initialize a MacOSInstaller using LoadMacOSRestoreImageFromPath function
// with the local restore image file.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func FetchLatestSupportedMacOSRestoreImage(ctx context.Context, destPath string) (*progress.Reader, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
waitCh := make(chan struct{})
var (
url string
fetchErr error
)
handler := macOSRestoreImageHandler(func(restoreImage *MacOSRestoreImage, err error) {
url = restoreImage.URL()
fetchErr = err
defer close(waitCh)
})
cgoHandler := cgo.NewHandle(handler)
C.fetchLatestSupportedMacOSRestoreImageWithCompletionHandler(
unsafe.Pointer(&cgoHandler),
)
<-waitCh
if fetchErr != nil {
return nil, fetchErr
}
progressReader, err := downloadRestoreImage(ctx, url, destPath)
if err != nil {
return nil, fmt.Errorf("failed to download from %q: %w", url, err)
}
return progressReader, nil
}
// LoadMacOSRestoreImageFromPath loads a macOS restore image from a filepath on the local file system.
//
// If the imagePath parameter doesnt refer to a local file, the system raises an exception via Objective-C.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func LoadMacOSRestoreImageFromPath(imagePath string) (retImage *MacOSRestoreImage, retErr error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
if _, err := os.Stat(imagePath); err != nil {
return nil, err
}
waitCh := make(chan struct{})
handler := macOSRestoreImageHandler(func(restoreImage *MacOSRestoreImage, err error) {
retImage = restoreImage
retErr = err
close(waitCh)
})
cgoHandler := cgo.NewHandle(handler)
cs := charWithGoString(imagePath)
defer cs.Free()
C.loadMacOSRestoreImageFile(cs.CString(), unsafe.Pointer(&cgoHandler))
<-waitCh
return
}
// MacOSInstaller is a struct you use to install macOS on the specified virtual machine.
type MacOSInstaller struct {
*pointer
observerPointer *pointer
vm *VirtualMachine
progress atomic.Value
doneCh chan struct{}
once sync.Once
err error
}
// NewMacOSInstaller creates a new MacOSInstaller struct.
//
// A param vm is the virtual machine that the operating system will be installed onto.
// A param restoreImageIpsw is a file path indicating the macOS restore image to install.
//
// This is only supported on macOS 12 and newer, error will
// be returned on older versions.
func NewMacOSInstaller(vm *VirtualMachine, restoreImageIpsw string) (*MacOSInstaller, error) {
if err := macOSAvailable(12); err != nil {
return nil, err
}
if _, err := os.Stat(restoreImageIpsw); err != nil {
return nil, err
}
cs := charWithGoString(restoreImageIpsw)
defer cs.Free()
ret := &MacOSInstaller{
pointer: objc.NewPointer(
C.newVZMacOSInstaller(objc.Ptr(vm), vm.dispatchQueue, cs.CString()),
),
observerPointer: objc.NewPointer(
C.newProgressObserverVZMacOSInstaller(),
),
vm: vm,
doneCh: make(chan struct{}),
}
ret.setFractionCompleted(0)
objc.SetFinalizer(ret, func(self *MacOSInstaller) {
objc.Release(self.observerPointer)
objc.Release(self)
})
return ret, nil
}
//export macOSInstallCompletionHandler
func macOSInstallCompletionHandler(cgoHandlerPtr, errPtr unsafe.Pointer) {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
handler := cgoHandler.Value().(func(error))
defer cgoHandler.Delete()
if err := newNSError(errPtr); err != nil {
handler(err)
} else {
handler(nil)
}
}
//export macOSInstallFractionCompletedHandler
func macOSInstallFractionCompletedHandler(cgoHandlerPtr unsafe.Pointer, completed C.double) {
cgoHandler := *(*cgo.Handle)(cgoHandlerPtr)
handler := cgoHandler.Value().(func(float64))
handler(float64(completed))
}
// Install starts installing macOS.
//
// This method starts the installation process. The VM must be in a stopped state.
// During the installation operation, pausing or stopping the VM results in an undefined behavior.
func (m *MacOSInstaller) Install(ctx context.Context) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
m.once.Do(func() {
completionHandler := cgo.NewHandle(func(err error) {
m.err = err
close(m.doneCh)
})
fractionCompletedHandler := cgo.NewHandle(func(v float64) {
m.setFractionCompleted(v)
})
C.installByVZMacOSInstaller(
objc.Ptr(m),
m.vm.dispatchQueue,
objc.Ptr(m.observerPointer),
unsafe.Pointer(&completionHandler),
unsafe.Pointer(&fractionCompletedHandler),
)
})
select {
case <-ctx.Done():
C.cancelInstallVZMacOSInstaller(objc.Ptr(m))
return ctx.Err()
case <-m.doneCh:
}
return m.err
}
func (m *MacOSInstaller) setFractionCompleted(completed float64) {
m.progress.Store(completed)
}
// FractionCompleted returns the fraction of the overall work that the install process
// completes.
func (m *MacOSInstaller) FractionCompleted() float64 {
return m.progress.Load().(float64)
}
// Done recieves a notification that indicates the install process is completed.
func (m *MacOSInstaller) Done() <-chan struct{} { return m.doneCh }

View File

@@ -0,0 +1,25 @@
//
// virtualization_debug.h
//
// Created by codehex.
//
#pragma once
#import <Foundation/Foundation.h>
#import <Virtualization/Virtualization.h>
@interface _VZDebugStubConfiguration : NSObject <NSCopying>
@end
@interface _VZGDBDebugStubConfiguration : NSObject <NSCopying>
@property NSInteger port;
- (instancetype)initWithPort:(NSInteger)port;
@end
@interface VZVirtualMachineConfiguration ()
- (void)_setDebugStub:(_VZDebugStubConfiguration *)config;
@end
void *newVZGDBDebugStubConfiguration(uint32_t port);
void setDebugStubVZVirtualMachineConfiguration(void *config, void *debugStub);

View File

@@ -0,0 +1,33 @@
//
// virtualization_debug.m
//
// Created by codehex.
//
#import "virtualization_debug.h"
#import "virtualization_helper.h"
/*!
@abstract Create a VZGDBDebugStubConfiguration with debug port for GDB server.
*/
void *newVZGDBDebugStubConfiguration(uint32_t port)
{
if (@available(macOS 12, *)) {
return [[_VZGDBDebugStubConfiguration alloc] initWithPort:(NSInteger)port];
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}
/*!
@abstract _VZDebugStubConfiguration. Empty by default.
*/
void setDebugStubVZVirtualMachineConfiguration(void *config, void *debugStub)
{
if (@available(macOS 12, *)) {
[(VZVirtualMachineConfiguration *)config _setDebugStub:(_VZDebugStubConfiguration *)debugStub];
return;
}
RAISE_UNSUPPORTED_MACOS_EXCEPTION();
}

View File

@@ -0,0 +1,59 @@
#pragma once
#import <Availability.h>
#import <Foundation/Foundation.h>
NSDictionary *dumpProcessinfo();
#define RAISE_REASON_MESSAGE \
"This may possibly be a bug due to library handling errors.\n" \
"I would appreciate it if you could report it to https://github.com/Code-Hex/vz/issues/new/choose\n\n" \
"Information: %@\n"
#define RAISE_UNSUPPORTED_MACOS_EXCEPTION() \
do { \
[NSException \
raise:@"UnhandledAvailabilityException" \
format:@RAISE_REASON_MESSAGE, dumpProcessinfo()]; \
__builtin_unreachable(); \
} while (0)
// for macOS 12.3 API
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 120300
#define INCLUDE_TARGET_OSX_12_3 1
#else
#pragma message("macOS 12.3 API has been disabled")
#endif
// for macOS 13 API
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 130000
#define INCLUDE_TARGET_OSX_13 1
#else
#pragma message("macOS 13 API has been disabled")
#endif
static inline int mac_os_x_version_max_allowed()
{
#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
return __MAC_OS_X_VERSION_MAX_ALLOWED;
#else
return 0;
#endif
}
typedef struct nbyteslice {
void *ptr;
int len;
} nbyteslice;
/* exported from cgo */
void virtualMachineCompletionHandler(void *cgoHandler, void *errPtr);
typedef void (^vm_completion_handler_t)(NSError *);
static inline vm_completion_handler_t makeVMCompletionHandler(void *completionHandler)
{
return Block_copy(^(NSError *err) {
virtualMachineCompletionHandler(completionHandler, err);
});
}

View File

@@ -0,0 +1,30 @@
//
// virtualization_helper.m
//
// Created by codehex.
//
#import "virtualization_helper.h"
#ifdef __arm64__
#define TARGET_ARM64 1
#else
#define TARGET_ARM64 0
#endif
NSDictionary *dumpProcessinfo()
{
NSString *osVersionString = [[NSProcessInfo processInfo] operatingSystemVersionString];
return @{
@"LLVM (Clang) Version" : @__VERSION__,
@"Target for arm64" : @TARGET_ARM64,
// The version of the macOS on which the process is executing.
@"Running OS Version" : osVersionString,
#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
@"Max Allowed OS Version" : @__MAC_OS_X_VERSION_MAX_ALLOWED,
#endif
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
@"Min Required OS Version" : @__MAC_OS_X_VERSION_MIN_REQUIRED,
#endif
};
}

View File

@@ -0,0 +1,31 @@
//
// virtualization_view.h
//
// Created by codehex.
//
#pragma once
#import <Availability.h>
#import <Cocoa/Cocoa.h>
#import <Virtualization/Virtualization.h>
@interface VZApplication : NSApplication {
bool shouldKeepRunning;
}
@end
@interface AboutViewController : NSViewController
- (instancetype)init;
@end
@interface AboutPanel : NSPanel
- (instancetype)init;
@end
API_AVAILABLE(macos(12.0))
@interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate, VZVirtualMachineDelegate>
- (instancetype)initWithVirtualMachine:(VZVirtualMachine *)virtualMachine
windowWidth:(CGFloat)windowWidth
windowHeight:(CGFloat)windowHeight;
@end

View File

@@ -0,0 +1,374 @@
//
// virtualization_view.m
//
// Created by codehex.
//
#import "virtualization_view.h"
@implementation VZApplication
- (void)run
{
@autoreleasepool {
[self finishLaunching];
shouldKeepRunning = YES;
do {
NSEvent *event = [self
nextEventMatchingMask:NSEventMaskAny
untilDate:[NSDate distantFuture]
inMode:NSDefaultRunLoopMode
dequeue:YES];
// NSLog(@"event: %@", event);
[self sendEvent:event];
[self updateWindows];
} while (shouldKeepRunning);
}
}
- (void)terminate:(id)sender
{
shouldKeepRunning = NO;
// We should call this method if we want to use `applicationWillTerminate` method.
//
// [[NSNotificationCenter defaultCenter]
// postNotificationName:NSApplicationWillTerminateNotification
// object:NSApp];
// This method is used to end up the event loop.
// If no events are coming, the event loop will always be in a waiting state.
[self postEvent:self.currentEvent atStart:NO];
}
@end
@implementation AboutViewController
- (instancetype)init
{
self = [super initWithNibName:nil bundle:nil];
return self;
}
- (void)loadView
{
self.view = [NSView new];
NSImageView *imageView = [NSImageView imageViewWithImage:[NSApp applicationIconImage]];
NSTextField *appLabel = [self makeLabel:[[NSProcessInfo processInfo] processName]];
[appLabel setFont:[NSFont boldSystemFontOfSize:16]];
NSTextField *subLabel = [self makePoweredByLabel];
NSStackView *stackView = [NSStackView stackViewWithViews:@[
imageView,
appLabel,
subLabel,
]];
[stackView setOrientation:NSUserInterfaceLayoutOrientationVertical];
[stackView setDistribution:NSStackViewDistributionFillProportionally];
[stackView setSpacing:10];
[stackView setAlignment:NSLayoutAttributeCenterX];
[stackView setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal];
[stackView setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationVertical];
[self.view addSubview:stackView];
[NSLayoutConstraint activateConstraints:@[
[imageView.widthAnchor constraintEqualToConstant:80], // image size
[imageView.heightAnchor constraintEqualToConstant:80], // image size
[stackView.topAnchor constraintEqualToAnchor:self.view.topAnchor
constant:4],
[stackView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor
constant:-16],
[stackView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor
constant:32],
[stackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor
constant:-32],
[stackView.widthAnchor constraintEqualToConstant:300]
]];
}
- (NSTextField *)makePoweredByLabel
{
NSMutableAttributedString *poweredByAttr = [[[NSMutableAttributedString alloc]
initWithString:@"Powered by "
attributes:@{
NSForegroundColorAttributeName : [NSColor labelColor]
}] autorelease];
NSURL *repositoryURL = [NSURL URLWithString:@"https://github.com/Code-Hex/vz"];
NSMutableAttributedString *repository = [self makeHyperLink:@"github.com/Code-Hex/vz" withURL:repositoryURL];
[poweredByAttr appendAttributedString:repository];
[poweredByAttr addAttribute:NSFontAttributeName
value:[NSFont systemFontOfSize:12]
range:NSMakeRange(0, [poweredByAttr length])];
NSTextField *label = [self makeLabel:@""];
[label setSelectable:YES];
[label setAllowsEditingTextAttributes:YES];
[label setAttributedStringValue:poweredByAttr];
return label;
}
- (NSTextField *)makeLabel:(NSString *)label
{
NSTextField *appLabel = [NSTextField labelWithString:label];
[appLabel setTextColor:[NSColor labelColor]];
[appLabel setEditable:NO];
[appLabel setSelectable:NO];
[appLabel setBezeled:NO];
[appLabel setBordered:NO];
[appLabel setBackgroundColor:[NSColor clearColor]];
[appLabel setAlignment:NSTextAlignmentCenter];
[appLabel setLineBreakMode:NSLineBreakByWordWrapping];
[appLabel setUsesSingleLineMode:NO];
[appLabel setMaximumNumberOfLines:20];
return appLabel;
}
// https://developer.apple.com/library/archive/qa/qa1487/_index.html
- (NSMutableAttributedString *)makeHyperLink:(NSString *)inString withURL:(NSURL *)aURL
{
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:inString];
NSRange range = NSMakeRange(0, [attrString length]);
[attrString beginEditing];
[attrString addAttribute:NSLinkAttributeName value:[aURL absoluteString] range:range];
// make the text appear in blue
[attrString addAttribute:NSForegroundColorAttributeName value:[NSColor blueColor] range:range];
// next make the text appear with an underline
[attrString addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:NSUnderlineStyleSingle]
range:range];
[attrString endEditing];
return [attrString autorelease];
}
@end
@implementation AboutPanel
- (instancetype)init
{
self = [super initWithContentRect:NSZeroRect styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:NO];
AboutViewController *viewController = [[[AboutViewController alloc] init] autorelease];
[self setContentViewController:viewController];
[self setTitleVisibility:NSWindowTitleHidden];
[self setTitlebarAppearsTransparent:YES];
[self setBecomesKeyOnlyIfNeeded:NO];
[self center];
return self;
}
@end
@implementation AppDelegate {
VZVirtualMachine *_virtualMachine;
VZVirtualMachineView *_virtualMachineView;
CGFloat _windowWidth;
CGFloat _windowHeight;
}
- (instancetype)initWithVirtualMachine:(VZVirtualMachine *)virtualMachine
windowWidth:(CGFloat)windowWidth
windowHeight:(CGFloat)windowHeight
{
self = [super init];
_virtualMachine = virtualMachine;
_virtualMachine.delegate = self;
// Setup virtual machine view configs
VZVirtualMachineView *view = [[[VZVirtualMachineView alloc] init] autorelease];
view.capturesSystemKeys = YES;
view.virtualMachine = _virtualMachine;
_virtualMachineView = view;
// Setup some window configs
_windowWidth = windowWidth;
_windowHeight = windowHeight;
return self;
}
/* IMPORTANT: delegate methods are called from VM's queue */
- (void)guestDidStopVirtualMachine:(VZVirtualMachine *)virtualMachine
{
[NSApp performSelectorOnMainThread:@selector(terminate:) withObject:self waitUntilDone:NO];
}
- (void)virtualMachine:(VZVirtualMachine *)virtualMachine didStopWithError:(NSError *)error
{
NSLog(@"VM %@ didStopWithError: %@", virtualMachine, error);
[NSApp performSelectorOnMainThread:@selector(terminate:) withObject:self waitUntilDone:NO];
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
[self setupMenuBar];
[self setupGraphicWindow];
// These methods are required to call here. Because the menubar will be not active even if
// application is running.
// See: https://stackoverflow.com/questions/62739862/why-doesnt-activateignoringotherapps-enable-the-menu-bar
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp activateIgnoringOtherApps:YES];
}
- (void)windowWillClose:(NSNotification *)notification
{
[NSApp performSelectorOnMainThread:@selector(terminate:) withObject:self waitUntilDone:NO];
}
- (void)setupGraphicWindow
{
NSRect rect = NSMakeRect(0, 0, _windowWidth, _windowHeight);
NSWindow *window = [[[NSWindow alloc] initWithContentRect:rect
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable //|NSTexturedBackgroundWindowMask
backing:NSBackingStoreBuffered
defer:NO] autorelease];
[window setOpaque:NO];
[window setContentView:_virtualMachineView];
[window setTitleVisibility:NSWindowTitleHidden];
[window center];
[window setDelegate:self];
[window makeKeyAndOrderFront:nil];
// This code to prevent crash when called applicationShouldTerminateAfterLastWindowClosed.
// https://stackoverflow.com/a/13470694
[window setReleasedWhenClosed:NO];
}
- (void)setupMenuBar
{
NSMenu *menuBar = [[[NSMenu alloc] init] autorelease];
NSMenuItem *menuBarItem = [[[NSMenuItem alloc] init] autorelease];
[menuBar addItem:menuBarItem];
[NSApp setMainMenu:menuBar];
// App menu
NSMenu *appMenu = [self setupApplicationMenu];
[menuBarItem setSubmenu:appMenu];
// Window menu
NSMenu *windowMenu = [self setupWindowMenu];
NSMenuItem *windowMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""] autorelease];
[menuBar addItem:windowMenuItem];
[windowMenuItem setSubmenu:windowMenu];
// Help menu
NSMenu *helpMenu = [self setupHelpMenu];
NSMenuItem *helpMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Help" action:nil keyEquivalent:@""] autorelease];
[menuBar addItem:helpMenuItem];
[helpMenuItem setSubmenu:helpMenu];
}
- (NSMenu *)setupApplicationMenu
{
NSMenu *appMenu = [[[NSMenu alloc] init] autorelease];
NSString *applicationName = [[NSProcessInfo processInfo] processName];
NSMenuItem *aboutMenuItem = [[[NSMenuItem alloc]
initWithTitle:[NSString stringWithFormat:@"About %@", applicationName]
action:@selector(openAboutWindow:)
keyEquivalent:@""] autorelease];
// CapturesSystemKeys toggle
NSMenuItem *capturesSystemKeysItem = [[[NSMenuItem alloc]
initWithTitle:@"Enable to send system hot keys to virtual machine"
action:@selector(toggleCapturesSystemKeys:)
keyEquivalent:@""] autorelease];
[capturesSystemKeysItem setState:[self capturesSystemKeysState]];
// Service menu
NSMenuItem *servicesMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Services" action:nil keyEquivalent:@""] autorelease];
NSMenu *servicesMenu = [[[NSMenu alloc] initWithTitle:@"Services"] autorelease];
[servicesMenuItem setSubmenu:servicesMenu];
[NSApp setServicesMenu:servicesMenu];
NSMenuItem *hideOthersItem = [[[NSMenuItem alloc]
initWithTitle:@"Hide Others"
action:@selector(hideOtherApplications:)
keyEquivalent:@"h"] autorelease];
[hideOthersItem setKeyEquivalentModifierMask:(NSEventModifierFlagOption | NSEventModifierFlagCommand)];
NSArray *menuItems = @[
aboutMenuItem,
[NSMenuItem separatorItem],
capturesSystemKeysItem,
[NSMenuItem separatorItem],
servicesMenuItem,
[NSMenuItem separatorItem],
[[[NSMenuItem alloc]
initWithTitle:[@"Hide " stringByAppendingString:applicationName]
action:@selector(hide:)
keyEquivalent:@"h"] autorelease],
hideOthersItem,
[NSMenuItem separatorItem],
[[[NSMenuItem alloc]
initWithTitle:[@"Quit " stringByAppendingString:applicationName]
action:@selector(terminate:)
keyEquivalent:@"q"] autorelease],
];
for (NSMenuItem *menuItem in menuItems) {
[appMenu addItem:menuItem];
}
return appMenu;
}
- (NSMenu *)setupWindowMenu
{
NSMenu *windowMenu = [[[NSMenu alloc] initWithTitle:@"Window"] autorelease];
NSArray *menuItems = @[
[[[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"] autorelease],
[[[NSMenuItem alloc] initWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""] autorelease],
[NSMenuItem separatorItem],
[[[NSMenuItem alloc] initWithTitle:@"Bring All to Front" action:@selector(arrangeInFront:) keyEquivalent:@""] autorelease],
];
for (NSMenuItem *menuItem in menuItems) {
[windowMenu addItem:menuItem];
}
[NSApp setWindowsMenu:windowMenu];
return windowMenu;
}
- (NSMenu *)setupHelpMenu
{
NSMenu *helpMenu = [[[NSMenu alloc] initWithTitle:@"Help"] autorelease];
NSArray *menuItems = @[
[[[NSMenuItem alloc] initWithTitle:@"Report issue" action:@selector(reportIssue:) keyEquivalent:@""] autorelease],
];
for (NSMenuItem *menuItem in menuItems) {
[helpMenu addItem:menuItem];
}
[NSApp setHelpMenu:helpMenu];
return helpMenu;
}
- (void)toggleCapturesSystemKeys:(id)sender
{
NSMenuItem *item = (NSMenuItem *)sender;
_virtualMachineView.capturesSystemKeys = !_virtualMachineView.capturesSystemKeys;
[item setState:[self capturesSystemKeysState]];
}
- (NSControlStateValue)capturesSystemKeysState
{
return _virtualMachineView.capturesSystemKeys ? NSControlStateValueOn : NSControlStateValueOff;
}
- (void)reportIssue:(id)sender
{
NSString *url = @"https://github.com/Code-Hex/vz/issues/new";
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:url]];
}
- (void)openAboutWindow:(id)sender
{
AboutPanel *aboutPanel = [[[AboutPanel alloc] init] autorelease];
[aboutPanel makeKeyAndOrderFront:nil];
}
@end

View File

@@ -0,0 +1,30 @@
// Code generated by "stringer -type=VirtualMachineState"; DO NOT EDIT.
package vz
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[VirtualMachineStateStopped-0]
_ = x[VirtualMachineStateRunning-1]
_ = x[VirtualMachineStatePaused-2]
_ = x[VirtualMachineStateError-3]
_ = x[VirtualMachineStateStarting-4]
_ = x[VirtualMachineStatePausing-5]
_ = x[VirtualMachineStateResuming-6]
_ = x[VirtualMachineStateStopping-7]
}
const _VirtualMachineState_name = "VirtualMachineStateStoppedVirtualMachineStateRunningVirtualMachineStatePausedVirtualMachineStateErrorVirtualMachineStateStartingVirtualMachineStatePausingVirtualMachineStateResumingVirtualMachineStateStopping"
var _VirtualMachineState_index = [...]uint8{0, 26, 52, 77, 101, 128, 154, 181, 208}
func (i VirtualMachineState) String() string {
if i < 0 || i >= VirtualMachineState(len(_VirtualMachineState_index)-1) {
return "VirtualMachineState(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _VirtualMachineState_name[_VirtualMachineState_index[i]:_VirtualMachineState_index[i+1]]
}

View File

@@ -0,0 +1,77 @@
package vz
// Error type returned by the Virtualization framework.
// The NSError domain is VZErrorDomain, the code is one of the ErrorCode constants.
//
//go:generate stringer -type=ErrorCode
type ErrorCode int
const (
// ErrorInternal is an internal error such as the virtual machine unexpectedly stopping.
ErrorInternal ErrorCode = 1 + iota
// ErrorInvalidVirtualMachineConfiguration represents invalid machine configuration.
ErrorInvalidVirtualMachineConfiguration
// ErrorInvalidVirtualMachineState represents API used with a machine in the wrong state
// (e.g. interacting with a machine before it is running).
ErrorInvalidVirtualMachineState
// ErrorInvalidVirtualMachineStateTransition is invalid change of state
// (e.g. pausing a virtual machine that is not started).
ErrorInvalidVirtualMachineStateTransition
// ErrorInvalidDiskImage represents unrecognized disk image format or invalid disk image.
ErrorInvalidDiskImage
// ErrorVirtualMachineLimitExceeded represents the running virtual machine limit was exceeded.
// Available from macOS 12.0 and above.
ErrorVirtualMachineLimitExceeded
// ErrorNetworkError represents network error occurred.
// Available from macOS 13.0 and above.
ErrorNetworkError
// ErrorOutOfDiskSpace represents machine ran out of disk space.
// Available from macOS 13.0 and above.
ErrorOutOfDiskSpace
// ErrorOperationCancelled represents the operation was cancelled.
// Available from macOS 13.0 and above.
ErrorOperationCancelled
// ErrorNotSupported represents the operation is not supported.
// Available from macOS 13.0 and above.
ErrorNotSupported
)
/* macOS installation errors. */
const (
// ErrorRestoreImageCatalogLoadFailed represents the restore image catalog failed to load.
// Available from macOS 13.0 and above.
ErrorRestoreImageCatalogLoadFailed ErrorCode = 10001 + iota
// ErrorInvalidRestoreImageCatalog represents the restore image catalog is invalid.
// Available from macOS 13.0 and above.
ErrorInvalidRestoreImageCatalog
// ErrorNoSupportedRestoreImagesInCatalog represents the restore image catalog has no supported restore images.
// Available from macOS 13.0 and above.
ErrorNoSupportedRestoreImagesInCatalog
// ErrorRestoreImageLoadFailed represents the restore image failed to load.
// Available from macOS 13.0 and above.
ErrorRestoreImageLoadFailed
// ErrorInvalidRestoreImage represents the restore image is invalid.
// Available from macOS 13.0 and above.
ErrorInvalidRestoreImage
// ErrorInstallationRequiresUpdate represents a software update is required to complete the installation.
// Available from macOS 13.0 and above.
ErrorInstallationRequiresUpdate
// ErrorInstallationFailed is an error occurred during installation.
// Available from macOS 13.0 and above.
ErrorInstallationFailed
)

Some files were not shown because too many files have changed in this diff Show More