diff --git a/cmd/libvirt-provider/app/app.go b/cmd/libvirt-provider/app/app.go index d06dc379..a6721194 100644 --- a/cmd/libvirt-provider/app/app.go +++ b/cmd/libvirt-provider/app/app.go @@ -31,7 +31,6 @@ import ( libvirtutils "github.com/ironcore-dev/libvirt-provider/internal/libvirt/utils" "github.com/ironcore-dev/libvirt-provider/internal/mcr" "github.com/ironcore-dev/libvirt-provider/internal/networkinterfaceplugin" - "github.com/ironcore-dev/libvirt-provider/internal/oci" volumeplugin "github.com/ironcore-dev/libvirt-provider/internal/plugins/volume" "github.com/ironcore-dev/libvirt-provider/internal/plugins/volume/ceph" "github.com/ironcore-dev/libvirt-provider/internal/plugins/volume/emptydisk" @@ -40,6 +39,8 @@ import ( "github.com/ironcore-dev/libvirt-provider/internal/strategy" "github.com/ironcore-dev/provider-utils/eventutils/event" "github.com/ironcore-dev/provider-utils/eventutils/recorder" + ocihostutils "github.com/ironcore-dev/provider-utils/ociutils/host" + ociutils "github.com/ironcore-dev/provider-utils/ociutils/oci" hostutils "github.com/ironcore-dev/provider-utils/storeutils/host" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/spf13/cobra" @@ -220,7 +221,14 @@ func Run(ctx context.Context, opts Options) error { return err } - reg, err := remote.DockerRegistry(nil) + platform, err := ocihostutils.Platform() + if err != nil { + setupLog.Error(err, "failed to get host platform: %w", err) + return err + } + setupLog.Info("Current platform", "architecture", platform.Architecture) + + reg, err := remote.DockerRegistryWithPlatform(nil, platform) if err != nil { setupLog.Error(err, "failed to initialize registry") return err @@ -232,7 +240,7 @@ func Run(ctx context.Context, opts Options) error { return err } - imgCache, err := oci.NewLocalCache(log, reg, ociStore) + imgCache, err := ociutils.NewLocalCache(log, reg, ociStore, nil) if err != nil { setupLog.Error(err, "failed to initialize oci manager") return err diff --git a/go.mod b/go.mod index b1d10afb..72bfb169 100644 --- a/go.mod +++ b/go.mod @@ -6,29 +6,27 @@ toolchain go1.24.1 require ( github.com/blang/semver/v4 v4.0.0 - github.com/containerd/containerd v1.7.28 github.com/digitalocean/go-libvirt v0.0.0-20250616175656-5843751af96c github.com/go-chi/chi/v5 v5.2.3 github.com/go-logr/logr v1.4.3 github.com/google/uuid v1.6.0 github.com/ironcore-dev/controller-utils v0.10.0 - github.com/ironcore-dev/ironcore v0.2.4-0.20250704085741-9036bfe3b718 - github.com/ironcore-dev/ironcore-image v0.2.4 + github.com/ironcore-dev/ironcore v0.2.4 + github.com/ironcore-dev/ironcore-image v0.2.5 github.com/ironcore-dev/ironcore-net v0.2.3 - github.com/ironcore-dev/provider-utils v0.0.0-20250829073857-ee02a09dd769 + github.com/ironcore-dev/provider-utils v0.0.0-20251010114402-394db8015df4 github.com/moby/term v0.5.2 - github.com/onsi/ginkgo/v2 v2.25.3 + github.com/onsi/ginkgo/v2 v2.26.0 github.com/onsi/gomega v1.38.2 - github.com/opencontainers/image-spec v1.1.1 github.com/prometheus/client_golang v1.23.2 github.com/shirou/gopsutil/v3 v3.24.5 github.com/spf13/cobra v1.10.1 github.com/spf13/pflag v1.0.10 golang.org/x/sync v0.17.0 google.golang.org/grpc v1.75.1 - k8s.io/api v0.33.3 - k8s.io/apimachinery v0.33.3 - k8s.io/client-go v0.33.3 + k8s.io/api v0.33.4 + k8s.io/apimachinery v0.33.4 + k8s.io/client-go v0.33.4 k8s.io/kubectl v0.33.3 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 libvirt.org/go/libvirtxml v1.11007.0 @@ -39,24 +37,21 @@ require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Masterminds/semver/v3 v3.4.0 // indirect - github.com/Microsoft/hcsshim v0.13.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/containerd/cgroups/v3 v3.0.5 // indirect - github.com/containerd/continuity v0.4.5 // indirect + github.com/containerd/containerd v1.7.28 // indirect github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/creack/pty v1.1.21 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v28.0.1+incompatible // indirect + github.com/docker/cli v28.0.4+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v28.0.1+incompatible // indirect - github.com/docker/docker-credential-helpers v0.9.2 // indirect + github.com/docker/docker v28.0.4+incompatible // indirect + github.com/docker/docker-credential-helpers v0.9.3 // indirect github.com/docker/go-connections v0.5.0 // indirect - github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect @@ -71,7 +66,6 @@ require ( github.com/go-openapi/swag v0.23.1 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.7.0 // indirect @@ -88,12 +82,12 @@ require ( github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/spdystream v0.5.0 // indirect - github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_model v0.6.2 // indirect @@ -116,6 +110,7 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.41.0 // indirect + golang.org/x/mod v0.27.0 // indirect golang.org/x/net v0.43.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sys v0.35.0 // indirect @@ -129,7 +124,6 @@ require ( gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - gotest.tools/v3 v3.5.1 // indirect k8s.io/apiextensions-apiserver v0.33.3 // indirect k8s.io/apiserver v0.33.3 // indirect k8s.io/cli-runtime v0.33.3 // indirect @@ -139,5 +133,5 @@ require ( sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect - sigs.k8s.io/yaml v1.5.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/go.sum b/go.sum index 549085fc..cdf415e7 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,7 @@ github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7 github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= github.com/containerd/containerd v1.7.28 h1:Nsgm1AtcmEh4AHAJ4gGlNSaKgXiNccU270Dnf81FQ3c= @@ -40,6 +41,7 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -59,14 +61,14 @@ github.com/distribution/distribution/v3 v3.0.0-beta.1 h1:X+ELTxPuZ1Xe5MsD3kp2wfG github.com/distribution/distribution/v3 v3.0.0-beta.1/go.mod h1:O9O8uamhHzWWQVTjuQpyYUVm/ShPHPUDgvQMpHGVBDs= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v28.0.1+incompatible h1:g0h5NQNda3/CxIsaZfH4Tyf6vpxFth7PYl3hgCPOKzs= -github.com/docker/cli v28.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v28.0.4+incompatible h1:pBJSJeNd9QeIWPjRcV91RVJihd/TXB77q1ef64XEu4A= +github.com/docker/cli v28.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0= -github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.9.2 h1:50JF7ADQiHdAVBRtg/vy883Y4U5+5GmPOBNtUU+X+6A= -github.com/docker/docker-credential-helpers v0.9.2/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo= +github.com/docker/docker v28.0.4+incompatible h1:JNNkBctYKurkw6FrHfKqY0nKIDf5nrbxjVBtS+cdcok= +github.com/docker/docker v28.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8= +github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 h1:EHZfspsnLAz8Hzccd67D5abwLiqoqym2jz/jOS39mCk= @@ -87,6 +89,12 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU= github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= +github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= +github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= +github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= +github.com/gkampitakis/go-snaps v0.5.14 h1:3fAqdB6BCPKHDMHAKRwtPUwYexKtGrNuw8HX/T/4neo= +github.com/gkampitakis/go-snaps v0.5.14/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -111,6 +119,8 @@ github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDq github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -153,16 +163,22 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ironcore-dev/controller-utils v0.10.0 h1:nG+TsVMtxt6PLJrlLr2LePYd8cOxud+z76rhuy5gCOs= github.com/ironcore-dev/controller-utils v0.10.0/go.mod h1:ZGv1A78M0X2G20ex/7F5BbyHoG0+7U2IWfqvzHh8T+4= -github.com/ironcore-dev/ironcore v0.2.4-0.20250704085741-9036bfe3b718 h1:LMA5vZFwBJGxKr3vkW6GUmuWuBw3/Vs7unrQOEixbP8= -github.com/ironcore-dev/ironcore v0.2.4-0.20250704085741-9036bfe3b718/go.mod h1:g3fXOlcGnSyj5pYUTeMWonq5kY2SB9zDS6tYCXFu/So= -github.com/ironcore-dev/ironcore-image v0.2.4 h1:yzmnXnXPKXCfJIL8TmyapyHfK6gup8zA+WV9Kq9pYqA= -github.com/ironcore-dev/ironcore-image v0.2.4/go.mod h1:ZwUrZ+pZumYAu6F9RJYe04824Leylma3tvIkNANwiyE= +github.com/ironcore-dev/ironcore v0.2.4 h1:i/RqiMIdzaptuDR6EKSX9hbeolj7AfTuT+4v1ZC4Jeg= +github.com/ironcore-dev/ironcore v0.2.4/go.mod h1:idYH/uyjxsIx8k3PFfXNtwfEpF9bBzBNe0aJFpIZpxs= +github.com/ironcore-dev/ironcore-image v0.2.5 h1:ImJD3B1p1/JVs5vx7YB3c8dwH/EHyWOcgWUqhTUmsR0= +github.com/ironcore-dev/ironcore-image v0.2.5/go.mod h1:pQLc+7dzgjYORTpEM9ORM757Vm14EQRju9hsvR8VT/U= github.com/ironcore-dev/ironcore-net v0.2.3 h1:xn8+oFr7aQSmnMYymUoU/SCVTF7eeVPKQf5RPPPpU5I= github.com/ironcore-dev/ironcore-net v0.2.3/go.mod h1:1aj8WV/4HcBjYApvhHPgEjAY16Vpzvj8MMChhx2v0Zs= -github.com/ironcore-dev/provider-utils v0.0.0-20250829073857-ee02a09dd769 h1:r9ZLt+wTd8XoqrNZ/ScaVW9mB1UVHAHoaj0mu+Gk35c= -github.com/ironcore-dev/provider-utils v0.0.0-20250829073857-ee02a09dd769/go.mod h1:+Sf2kEayq93OkRXVFNhRYmfSHdVl8LtcTL9d5FbNxsI= +github.com/ironcore-dev/provider-utils v0.0.0-20251007110633-878bf03490a5 h1:cGcc/707upUM1o+dS0OZ4eAUKa3q1pLzYZ+PJr5o/Io= +github.com/ironcore-dev/provider-utils v0.0.0-20251007110633-878bf03490a5/go.mod h1:qxuFuJy31Lfu3go5wsGpFGAZwCw1++1EKGJmHG2HbLw= +github.com/ironcore-dev/provider-utils v0.0.0-20251010113808-6143c908458b h1:/hxGrVIpdZg2hZZgr4E54sDS1pq35YSEAkInYqr2tZ0= +github.com/ironcore-dev/provider-utils v0.0.0-20251010113808-6143c908458b/go.mod h1:qxuFuJy31Lfu3go5wsGpFGAZwCw1++1EKGJmHG2HbLw= +github.com/ironcore-dev/provider-utils v0.0.0-20251010114402-394db8015df4 h1:sRQ/gcL5z3CqcqI+9If8XmgVk9pK4WebZOAMNFYXREQ= +github.com/ironcore-dev/provider-utils v0.0.0-20251010114402-394db8015df4/go.mod h1:qxuFuJy31Lfu3go5wsGpFGAZwCw1++1EKGJmHG2HbLw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= +github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -186,7 +202,11 @@ github.com/lufia/plan9stats v0.0.0-20250303091104-876f3ea5145d h1:fjMbDVUGsMQiVZ github.com/lufia/plan9stats v0.0.0-20250303091104-876f3ea5145d/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= +github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= +github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= @@ -211,8 +231,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/onsi/ginkgo/v2 v2.25.3 h1:Ty8+Yi/ayDAGtk4XxmmfUy4GabvM+MegeB4cDLRi6nw= -github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy3bG/snE= +github.com/onsi/ginkgo/v2 v2.26.0 h1:1J4Wut1IlYZNEAWIV3ALrT9NfiaGW2cDCJQSFQMs/gE= +github.com/onsi/ginkgo/v2 v2.26.0/go.mod h1:qhEywmzWTBUY88kfO0BRvX4py7scov9yR+Az2oavUzw= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -255,8 +275,8 @@ github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY= github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= @@ -281,6 +301,14 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= @@ -349,6 +377,8 @@ golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -426,18 +456,18 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8= -k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE= +k8s.io/api v0.33.4 h1:oTzrFVNPXBjMu0IlpA2eDDIU49jsuEorGHB4cvKupkk= +k8s.io/api v0.33.4/go.mod h1:VHQZ4cuxQ9sCUMESJV5+Fe8bGnqAARZ08tSTdHWfeAc= k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs= k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8= -k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= -k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/apimachinery v0.33.4 h1:SOf/JW33TP0eppJMkIgQ+L6atlDiP/090oaX0y9pd9s= +k8s.io/apimachinery v0.33.4/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= k8s.io/apiserver v0.33.3 h1:Wv0hGc+QFdMJB4ZSiHrCgN3zL3QRatu56+rpccKC3J4= k8s.io/apiserver v0.33.3/go.mod h1:05632ifFEe6TxwjdAIrwINHWE2hLwyADFk5mBsQa15E= k8s.io/cli-runtime v0.33.3 h1:Dgy4vPjNIu8LMJBSvs8W0LcdV0PX/8aGG1DA1W8lklA= k8s.io/cli-runtime v0.33.3/go.mod h1:yklhLklD4vLS8HNGgC9wGiuHWze4g7x6XQZ+8edsKEo= -k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA= -k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg= +k8s.io/client-go v0.33.4 h1:TNH+CSu8EmXfitntjUPwaKVPN0AYMbc9F1bBS8/ABpw= +k8s.io/client-go v0.33.4/go.mod h1:LsA0+hBG2DPwovjd931L/AoaezMPX9CmBgyVyBZmbCY= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250610211856-8b98d1ed966a h1:ZV3Zr+/7s7aVbjNGICQt+ppKWsF1tehxggNfbM7XnG8= @@ -460,5 +490,5 @@ sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxO sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= -sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= -sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/internal/controllers/machine_controller.go b/internal/controllers/machine_controller.go index 25e81eea..ac628e47 100644 --- a/internal/controllers/machine_controller.go +++ b/internal/controllers/machine_controller.go @@ -23,7 +23,6 @@ import ( "github.com/ironcore-dev/libvirt-provider/internal/libvirt/guest" libvirtmeta "github.com/ironcore-dev/libvirt-provider/internal/libvirt/meta" libvirtutils "github.com/ironcore-dev/libvirt-provider/internal/libvirt/utils" - providerimage "github.com/ironcore-dev/libvirt-provider/internal/oci" "github.com/ironcore-dev/libvirt-provider/internal/osutils" providernetworkinterface "github.com/ironcore-dev/libvirt-provider/internal/plugins/networkinterface" providervolume "github.com/ironcore-dev/libvirt-provider/internal/plugins/volume" @@ -31,6 +30,7 @@ import ( "github.com/ironcore-dev/libvirt-provider/internal/utils" "github.com/ironcore-dev/provider-utils/eventutils/event" "github.com/ironcore-dev/provider-utils/eventutils/recorder" + ociutils "github.com/ironcore-dev/provider-utils/ociutils/oci" "github.com/ironcore-dev/provider-utils/storeutils/store" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/wait" @@ -68,7 +68,7 @@ var ( type MachineReconcilerOptions struct { GuestCapabilities guest.Capabilities TCMallocLibPath string - ImageCache providerimage.Cache + ImageCache ociutils.Cache Raw raw.Raw VolumePluginManager *providervolume.PluginManager NetworkInterfacePlugin providernetworkinterface.Plugin @@ -104,7 +104,7 @@ func NewMachineReconciler( queue: workqueue.NewTypedRateLimitingQueue[string](workqueue.DefaultTypedControllerRateLimiter[string]()), machines: machines, machineEvents: machineEvents, - EventRecorder: eventRecorder, + eventRecorder: eventRecorder, guestCapabilities: opts.GuestCapabilities, tcMallocLibPath: opts.TCMallocLibPath, host: host, @@ -126,7 +126,7 @@ type MachineReconciler struct { guestCapabilities guest.Capabilities tcMallocLibPath string host providerhost.LibvirtHost - imageCache providerimage.Cache + imageCache ociutils.Cache raw raw.Raw enableHugepages bool @@ -136,7 +136,7 @@ type MachineReconciler struct { machines store.Store[*api.Machine] machineEvents event.Source[*api.Machine] - recorder.EventRecorder + eventRecorder recorder.EventRecorder gcVMGracefulShutdownTimeout time.Duration resyncIntervalGarbageCollector time.Duration @@ -150,8 +150,8 @@ func (r *MachineReconciler) Start(ctx context.Context) error { //todo make configurable workerSize := 15 - r.imageCache.AddListener(providerimage.ListenerFuncs{ - HandlePullDoneFunc: func(evt providerimage.PullDoneEvent) { + r.imageCache.AddListener(ociutils.ListenerFuncs{ + HandlePullDoneFunc: func(evt ociutils.PullDoneEvent) { machines, err := r.machines.List(ctx) if err != nil { log.Error(err, "failed to list machine") @@ -160,7 +160,7 @@ func (r *MachineReconciler) Start(ctx context.Context) error { for _, machine := range machines { if ptr.Deref(machine.Spec.Image, "") == evt.Ref { - r.Eventf(machine.Metadata, corev1.EventTypeNormal, "PulledImage", "Pulled image %s", *machine.Spec.Image) + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeNormal, "PulledImage", "Pulled image %s", *machine.Spec.Image) log.V(1).Info("Image pulled: Requeue machines", "Image", evt.Ref, "Machine", machine.ID) r.queue.Add(machine.ID) } @@ -304,7 +304,7 @@ func (r *MachineReconciler) processMachineDeletion(ctx context.Context, log logr if _, err := r.machines.Update(ctx, machine); store.IgnoreErrNotFound(err) != nil { return fmt.Errorf("failed to update machine metadata: %w", err) } - r.Eventf(machine.Metadata, corev1.EventTypeNormal, "CompletedDeletion", "Deletion completed") + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeNormal, "CompletedDeletion", "Deletion completed") log.V(1).Info("Removed Finalizer. Deletion completed") return nil @@ -343,7 +343,7 @@ func (r *MachineReconciler) destroyDomain(log logr.Logger, machine *api.Machine, return fmt.Errorf("failed to initiate forceful shutdown: %w", err) } - r.Eventf(machine.Metadata, corev1.EventTypeWarning, "DestroyedDomain", "Domain Destroyed") + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeWarning, "DestroyedDomain", "Domain Destroyed") log.V(1).Info("Destroyed domain") return nil @@ -351,7 +351,7 @@ func (r *MachineReconciler) destroyDomain(log logr.Logger, machine *api.Machine, func (r *MachineReconciler) shutdownMachine(log logr.Logger, machine *api.Machine, domain libvirt.Domain) (bool, error) { log.V(1).Info("Triggering shutdown", "ShutdownAt", machine.Spec.ShutdownAt) - r.Eventf(machine.Metadata, corev1.EventTypeNormal, "TriggeringShutdown", "Shutdown Triggered") + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeNormal, "TriggeringShutdown", "Shutdown Triggered") shutdownMode := libvirt.DomainShutdownAcpiPowerBtn if machine.Spec.GuestAgent == api.GuestAgentQemu { @@ -421,7 +421,7 @@ func (r *MachineReconciler) reconcileMachine(ctx context.Context, id string) err log.V(1).Info("Reconciling domain") state, volumeStates, nicStates, err := r.reconcileDomain(ctx, log, machine) if err != nil { - return providerimage.IgnoreImagePulling(err) + return ociutils.IgnoreImagePulling(err) } log.V(1).Info("Reconciled domain") @@ -488,13 +488,13 @@ func (r *MachineReconciler) updateDomain( volumeStates, err := r.attachDetachVolumes(ctx, log, machine, attacher) if err != nil { - r.Eventf(machine.Metadata, corev1.EventTypeWarning, "AttchDetachVolume", "Volume attach/detach failed with error: %s", err) + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeWarning, "AttchDetachVolume", "Volume attach/detach failed with error: %s", err) return nil, nil, fmt.Errorf("[volumes] %w", err) } nicStates, err := r.attachDetachNetworkInterfaces(ctx, log, machine, domainDesc) if err != nil { - r.Eventf(machine.Metadata, corev1.EventTypeWarning, "AttchDetachNIC", "NIC attach/detach failed with error: %s", err) + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeWarning, "AttchDetachNIC", "NIC attach/detach failed with error: %s", err) return nil, nil, fmt.Errorf("[network interfaces] %w", err) } @@ -701,7 +701,7 @@ func (r *MachineReconciler) domainFor( return nil, nil, nil, err } } else { - r.Eventf(machine.Metadata, corev1.EventTypeWarning, "NoIgnitionData", "Machine does not have ignition data") + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeWarning, "NoIgnitionData", "Machine does not have ignition data") } attacher, err := NewLibvirtVolumeAttacher(domainDesc, NewCreateDomainExecutor(r.host.Libvirt()), r.volumeCachePolicy) @@ -711,20 +711,20 @@ func (r *MachineReconciler) domainFor( volumeStates, err := r.attachDetachVolumes(ctx, log, machine, attacher) if err != nil { - r.Eventf(machine.Metadata, corev1.EventTypeWarning, "AttchDetachVolume", "Volume attach/detach failed with error: %s", err) + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeWarning, "AttchDetachVolume", "Volume attach/detach failed with error: %s", err) return nil, nil, nil, err } if machine.Spec.Volumes != nil { - r.Eventf(machine.Metadata, corev1.EventTypeNormal, "AttchedVolume", "Successfully attached volumes") + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeNormal, "AttchedVolume", "Successfully attached volumes") } nicStates, err := r.setDomainNetworkInterfaces(ctx, machine, domainDesc) if err != nil { - r.Eventf(machine.Metadata, corev1.EventTypeWarning, "AttchDetachNIC", "Setting domain network interface failed with error: %s", err) + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeWarning, "AttchDetachNIC", "Setting domain network interface failed with error: %s", err) return nil, nil, nil, err } if machine.Spec.NetworkInterfaces != nil { - r.Eventf(machine.Metadata, corev1.EventTypeNormal, "AttchedNIC", "Successfully attached network interfaces") + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeNormal, "AttchedNIC", "Successfully attached network interfaces") } return domainDesc, volumeStates, nicStates, nil @@ -849,11 +849,11 @@ func (r *MachineReconciler) setDomainImage( ) error { img, err := r.imageCache.Get(ctx, machineImgRef) if err != nil { - if !errors.Is(err, providerimage.ErrImagePulling) { + if !errors.Is(err, ociutils.ErrImagePulling) { return err } - r.Eventf(machine.Metadata, corev1.EventTypeNormal, "PullingImage", "Pulling image %s", machineImgRef) + r.eventRecorder.Eventf(machine.Metadata, corev1.EventTypeNormal, "PullingImage", "Pulling image %s", machineImgRef) return err } @@ -863,7 +863,7 @@ func (r *MachineReconciler) setDomainImage( return err } if !ok { - if err := r.raw.Create(rootFSFile, raw.WithSourceFile(img.SquashFS.Path)); err != nil { + if err := r.raw.Create(rootFSFile, raw.WithSourceFile(img.RootFS.Path)); err != nil { return fmt.Errorf("error creating root fs disk: %w", err) } if err := os.Chmod(rootFSFile, filePerm); err != nil { @@ -871,9 +871,6 @@ func (r *MachineReconciler) setDomainImage( } } - domain.OS.Kernel = img.Kernel.Path - domain.OS.Initrd = img.InitRAMFs.Path - domain.OS.Cmdline = img.Config.CommandLine domain.Devices.Disks = append(domain.Devices.Disks, libvirtxml.DomainDisk{ Alias: &libvirtxml.DomainAlias{ Name: rootFSAlias, diff --git a/internal/oci/image.go b/internal/oci/image.go deleted file mode 100644 index 98b6757a..00000000 --- a/internal/oci/image.go +++ /dev/null @@ -1,355 +0,0 @@ -// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors -// SPDX-License-Identifier: Apache-2.0 - -package oci - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "sync" - "time" - - "github.com/containerd/containerd/remotes" - "github.com/go-logr/logr" - ironcoreimage "github.com/ironcore-dev/ironcore-image" - "github.com/ironcore-dev/ironcore-image/oci/image" - "github.com/ironcore-dev/ironcore-image/oci/indexer" - "github.com/ironcore-dev/ironcore-image/oci/remote" - "github.com/ironcore-dev/ironcore-image/oci/store" - "github.com/ironcore-dev/ironcore-image/utils/sets" - ocispecv1 "github.com/opencontainers/image-spec/specs-go/v1" -) - -type Image struct { - Config ironcoreimage.Config - SquashFS *FileLayer - InitRAMFs *FileLayer - Kernel *FileLayer -} - -type FileLayer struct { - Descriptor ocispecv1.Descriptor - Path string -} - -type LocalCache struct { - mu sync.Mutex - running bool - - log logr.Logger - - store *store.Store - registry *remote.Registry - - pullRequests chan pullRequest - listeners []Listener -} - -type pullRequest struct { - ctx context.Context - ref string - res chan pullResult -} - -type pullResult struct { - image *Image - err error -} - -func readImageConfig(ctx context.Context, img image.Image) (*ironcoreimage.Config, error) { - configLayer, err := img.Config(ctx) - if err != nil { - return nil, fmt.Errorf("error getting config layer: %w", err) - } - - rc, err := configLayer.Content(ctx) - if err != nil { - return nil, fmt.Errorf("error getting config content: %w", err) - } - defer func() { _ = rc.Close() }() - - config := &ironcoreimage.Config{} - if err := json.NewDecoder(rc).Decode(config); err != nil { - return nil, fmt.Errorf("error decoding config: %w", err) - } - return config, nil -} - -func (c *LocalCache) resolveImage(ctx context.Context, ociImg image.Image) (*Image, error) { - config, err := readImageConfig(ctx, ociImg) - if err != nil { - return nil, err - } - - layers, err := ociImg.Layers(ctx) - if err != nil { - return nil, fmt.Errorf("error getting oci layers: %w", err) - } - - var ( - localStore = c.store.Layout().Store() - img = Image{Config: *config} - ) - for _, layer := range layers { - switch layer.Descriptor().MediaType { - case ironcoreimage.InitRAMFSLayerMediaType: - initRAMFSPath, err := localStore.BlobPath(layer.Descriptor().Digest) - if err != nil { - return nil, fmt.Errorf("error getting path to initramfs: %w", err) - } - img.InitRAMFs = &FileLayer{ - Descriptor: layer.Descriptor(), - Path: initRAMFSPath, - } - case ironcoreimage.KernelLayerMediaType: - kernelPath, err := localStore.BlobPath(layer.Descriptor().Digest) - if err != nil { - return nil, fmt.Errorf("error getting path to kernel: %w", err) - } - img.Kernel = &FileLayer{ - Descriptor: layer.Descriptor(), - Path: kernelPath, - } - case ironcoreimage.SquashFSLayerMediaType: - squashFSPath, err := localStore.BlobPath(layer.Descriptor().Digest) - if err != nil { - return nil, fmt.Errorf("error getting path to rootfs: %w", err) - } - img.SquashFS = &FileLayer{ - Descriptor: layer.Descriptor(), - Path: squashFSPath, - } - - } - } - var missing []string - if img.Kernel == nil || img.Kernel.Path == "" { - missing = append(missing, "kernel") - } - if img.SquashFS == nil || img.SquashFS.Path == "" { - missing = append(missing, "squashfs") - } - if img.InitRAMFs == nil || img.InitRAMFs.Path == "" { - missing = append(missing, "initramfs") - } - if len(missing) > 0 { - return nil, fmt.Errorf("incomplete oci: components are missing: %v", missing) - } - - return &img, nil -} - -func (c *LocalCache) loop(ctx context.Context) { - var ( - activePulls = sets.New[string]() - pullDone = make(chan string) - ) - - for { - select { - case <-ctx.Done(): - return - case ref := <-pullDone: - activePulls.Delete(ref) - for _, listener := range c.listeners { - listener.HandlePullDone(PullDoneEvent{Ref: ref}) - } - case req := <-c.pullRequests: - req.ctx = setupMediaTypeKeyPrefixes(ctx) - if activePulls.Has(req.ref) { - req.res <- pullResult{err: ErrImagePulling} - continue - } - - ociImg, err := c.store.Resolve(req.ctx, req.ref) - if err != nil { - if !errors.Is(err, indexer.ErrNotFound) { - req.res <- pullResult{err: fmt.Errorf("error pulling %s: %w", req.ref, err)} - } - - activePulls.Insert(req.ref) - go func() { - log := c.log.WithValues("Ref", req.ref) - defer func() { - select { - case pullDone <- req.ref: - case <-ctx.Done(): - } - }() - - log.V(1).Info("Start pulling") - err := c.retryPullImage(ctx, req.ref) - if err != nil { - log.Error(err, "Error copying oci") - return - } - log.V(1).Info("Successfully pulled") - }() - - req.res <- pullResult{err: ErrImagePulling} - continue - } - - img, err := c.resolveImage(req.ctx, ociImg) - req.res <- pullResult{image: img, err: err} - } - } -} - -func (c *LocalCache) retryPullImage(ctx context.Context, ref string) error { - var maxRetries = 5 - var errs []error - log := c.log.WithValues("Ref", ref).V(1) - - sleepDuration := 1 * time.Second - for i := 0; i < maxRetries; i++ { - if i > 0 { - sleepDuration <<= 2 - select { - case <-time.After(sleepDuration): - case <-ctx.Done(): - return ctx.Err() - } - } - - err := c.pullImage(ctx, ref) - if err == nil { - return nil - } - log.Error(err, "oci couldn't be pulled") - errs = append(errs, fmt.Errorf("trial %d of oci pull failed with: %w ", i+1, err)) - } - - return fmt.Errorf("exceeded max retries, oci pull failed with error(s): %v", errs) -} - -func (c *LocalCache) pullImage(ctx context.Context, ref string) error { - sourceImg, err := image.Copy(ctx, c.store, c.registry, ref) - if err != nil { - return err - } - ociImg, err := c.store.Resolve(ctx, ref) - if err != nil { - return fmt.Errorf("error resolving ref locally %s: %w", ref, err) - } - - srcDigest := sourceImg.Descriptor().Digest - copiedDigest := ociImg.Descriptor().Digest - - if srcDigest != copiedDigest { - if err = c.store.Delete(ctx, ref); err != nil { - return fmt.Errorf("error deleting oci from local oci store %s: %w", ref, err) - } - return fmt.Errorf("oci digest verification failed for oci %s: source digest %s, copied digest %s", ref, srcDigest, copiedDigest) - } - return nil -} - -var ErrImagePulling = errors.New("oci pulling") - -func IgnoreImagePulling(err error) error { - if errors.Is(err, ErrImagePulling) { - return nil - } - return err -} - -func setupMediaTypeKeyPrefixes(ctx context.Context) context.Context { - mediaTypeToPrefix := map[string]string{ - ironcoreimage.ConfigMediaType: "config", - ironcoreimage.InitRAMFSLayerMediaType: "layer", - ironcoreimage.KernelLayerMediaType: "layer", - ironcoreimage.RootFSLayerMediaType: "layer", - ironcoreimage.SquashFSLayerMediaType: "layer", - } - for mediaType, prefix := range mediaTypeToPrefix { - ctx = remotes.WithMediaTypeKeyPrefix(ctx, mediaType, prefix) - } - return ctx -} - -func (c *LocalCache) Start(ctx context.Context) error { - ctx = setupMediaTypeKeyPrefixes(ctx) - - c.mu.Lock() - if c.running { - c.mu.Unlock() - return fmt.Errorf("already running") - } - - c.running = true - c.mu.Unlock() - - defer func() { - c.mu.Lock() - defer c.mu.Unlock() - c.running = false - }() - c.loop(ctx) - - return nil -} - -func NewLocalCache(log logr.Logger, registry *remote.Registry, store *store.Store) (*LocalCache, error) { - return &LocalCache{ - log: log, - store: store, - registry: registry, - pullRequests: make(chan pullRequest), - }, nil -} - -type Cache interface { - Get(ctx context.Context, ref string) (*Image, error) - AddListener(listener Listener) -} - -type PullDoneEvent struct { - Ref string -} - -type Listener interface { - HandlePullDone(evt PullDoneEvent) -} - -type ListenerFuncs struct { - HandlePullDoneFunc func(evt PullDoneEvent) -} - -func (l ListenerFuncs) HandlePullDone(evt PullDoneEvent) { - if l.HandlePullDoneFunc != nil { - l.HandlePullDoneFunc(evt) - } -} - -func (c *LocalCache) Get(ctx context.Context, ref string) (*Image, error) { - c.mu.Lock() - running := c.running - c.mu.Unlock() - - if !running { - return nil, fmt.Errorf("need to start manager first") - } - - pullRes := make(chan pullResult, 1) - - select { - case <-ctx.Done(): - return nil, ctx.Err() - case c.pullRequests <- pullRequest{ctx, ref, pullRes}: - } - - // Once successfully submitted, it's expected to get a result that respects the given - // context.Context, hence we're just reading instead of doing a `select` with the context.Context of this - // function. - res := <-pullRes - return res.image, res.err -} - -func (c *LocalCache) AddListener(listener Listener) { - c.mu.Lock() - defer c.mu.Unlock() - c.listeners = append(c.listeners, listener) -} diff --git a/internal/server/machine_delete_test.go b/internal/server/machine_delete_test.go index 63ba9d1e..05df1445 100644 --- a/internal/server/machine_delete_test.go +++ b/internal/server/machine_delete_test.go @@ -106,7 +106,7 @@ var _ = Describe("DeleteMachine", func() { }) g.Expect(err).NotTo(HaveOccurred()) g.Expect(listResp.Machines).To(BeEmpty()) - }).Within(gracefulShutdownTimeout).ProbeEvery(probeEveryInterval).Should(Succeed()) // ProbeEvery has to be ideally less than or equal to half of ResyncIntervalGarbageCollector + }).Within(gracefulShutdownTimeout * 2).ProbeEvery(probeEveryInterval).Should(Succeed()) // ProbeEvery has to be ideally less than or equal to half of ResyncIntervalGarbageCollector By("ensuring domain and domain XML is deleted for machine") domain, err = libvirtConn.DomainLookupByUUID(libvirtutils.UUIDStringToBytes(createResp.Machine.Metadata.Id)) diff --git a/internal/server/machine_volume_detach_test.go b/internal/server/machine_volume_detach_test.go index 4c4a6a9c..b2385640 100644 --- a/internal/server/machine_volume_detach_test.go +++ b/internal/server/machine_volume_detach_test.go @@ -145,9 +145,6 @@ var _ = Describe("DetachVolume", func() { Expect(disks[1].Serial).To(HavePrefix("odb")) Expect(disks[2].Serial).To(HavePrefix("odc")) - // wait to complete machine reconciliation - time.Sleep(20 * time.Second) - By("detaching empty disk disk-1 from machine") diskDetachResp, err := machineClient.DetachVolume(ctx, &iri.DetachVolumeRequest{ MachineId: createResp.Machine.Metadata.Id, @@ -156,39 +153,6 @@ var _ = Describe("DetachVolume", func() { Expect(err).NotTo(HaveOccurred()) Expect(diskDetachResp).NotTo(BeNil()) - By("ensuring empty disk disk-1 is unplugged from a machine domain") - Eventually(func(g Gomega) int { - domainXMLData, err := libvirtConn.DomainGetXMLDesc(domain, 0) - g.Expect(err).NotTo(HaveOccurred()) - domainXML := &libvirtxml.Domain{} - err = domainXML.Unmarshal(domainXMLData) - g.Expect(err).NotTo(HaveOccurred()) - disks = domainXML.Devices.Disks - return len(disks) - }).Should(Equal(3)) - - // wait to complete machine reconciliation - time.Sleep(20 * time.Second) - - By("detaching ceph volume volume-1 from machine") - volumeDetachResp, err := machineClient.DetachVolume(ctx, &iri.DetachVolumeRequest{ - MachineId: createResp.Machine.Metadata.Id, - Name: "volume-1", - }) - Expect(err).NotTo(HaveOccurred()) - Expect(volumeDetachResp).NotTo(BeNil()) - - By("ensuring ceph volume volume-1 is unplugged from a machine domain") - Eventually(func(g Gomega) int { - domainXMLData, err := libvirtConn.DomainGetXMLDesc(domain, 0) - g.Expect(err).NotTo(HaveOccurred()) - domainXML := &libvirtxml.Domain{} - err = domainXML.Unmarshal(domainXMLData) - g.Expect(err).NotTo(HaveOccurred()) - disks = domainXML.Devices.Disks - return len(disks) - }).Should(Equal(2)) - By("ensuring detached disk and volume have been updated in machine status field") Eventually(func(g Gomega) *iri.MachineStatus { listResp, err := machineClient.ListMachines(ctx, &iri.ListMachinesRequest{ diff --git a/internal/server/server_suite_test.go b/internal/server/server_suite_test.go index 46cbc126..be336350 100644 --- a/internal/server/server_suite_test.go +++ b/internal/server/server_suite_test.go @@ -39,7 +39,7 @@ const ( probeEveryInterval = 2 * time.Second machineClassx3xlarge = "x3-xlarge" machineClassx2medium = "x2-medium" - osImage = "ghcr.io/ironcore-dev/os-images/gardenlinux-amd64:latest" + osImage = "ghcr.io/ironcore-dev/os-images/virtualization/gardenlinux:latest" emptyDiskSize = 1024 * 1024 * 1024 baseURL = "http://localhost:20251" streamingAddress = "127.0.0.1:20251"