diff --git a/Dockerfile b/Dockerfile index fb4ce186..335c01d4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,37 +30,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && update-ca-certificates \ && rm -rf /var/lib/apt/lists/* -# Install cross-compiler for ARM64 if building for arm64 on an amd64 host -RUN if [ "$TARGETARCH" = "arm64" ] && [ "$BUILDARCH" = "amd64" ]; then \ - dpkg --add-architecture arm64 && \ - apt-get update && apt-get install -y --no-install-recommends \ - gcc-aarch64-linux-gnu librbd-dev:arm64 librados-dev:arm64 libc6-dev:arm64; \ - fi -# Install cross-compiler for AMD64 if building for amd64 on an arm64 host -RUN if [ "$TARGETARCH" = "amd64" ] && [ "$BUILDARCH" = "arm64" ]; then \ - apt update && \ - apt-get install -y --no-install-recommends \ - gcc-x86-64-linux-gnu; \ - fi +RUN --mount=type=cache,target=/root/.cache/go-build \ + --mount=type=cache,target=/go/pkg \ + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags="-s -w" -a -o libvirt-provider ./cmd/libvirt-provider/main.go -# Set compiler and linker flags based on target architecture -ENV CC="" -ENV CGO_LDFLAGS="" - -RUN if [ "$TARGETARCH" != "$BUILDARCH" ] && [ "$TARGETARCH" = "arm64" ]; then \ - export CC="/usr/bin/aarch64-linux-gnu-gcc"; \ - export CGO_LDFLAGS="-L/usr/lib/aarch64-linux-gnu -Wl,-lrados -Wl,-lrbd"; \ - elif [ "$TARGETARCH" != "$BUILDARCH" ] && [ "$TARGETARCH" = "amd64" ]; then \ - export CC="/usr/bin/x86_64-linux-gnu-gcc"; \ - export CGO_LDFLAGS="-L/usr/lib/x86_64-linux-gnu -Wl,-lrados -Wl,-lrbd"; \ - else \ - export CC="/usr/bin/gcc"; \ - export CGO_LDFLAGS=""; \ - fi && \ - CGO_ENABLED=1 GOOS=$TARGETOS GOARCH=$TARGETARCH \ - CC="$CC" CGO_LDFLAGS="$CGO_LDFLAGS" \ - go build -ldflags="-s -w -linkmode=external" -o libvirt-provider ./cmd/libvirt-provider/main.go # Install irictl-machine RUN --mount=type=cache,target=/root/.cache/go-build \ @@ -75,63 +49,14 @@ RUN if [ "$TARGETARCH" = "$BUILDARCH" ]; then \ mv /go/bin/linux_$TARGETARCH/irictl-machine /workspace/irictl-machine; \ fi + +FROM busybox:1.37.0-uclibc AS busybox + # Since we're leveraging apt to pull in dependencies, we use `gcr.io/distroless/base` because it includes glibc. -FROM gcr.io/distroless/base-debian11 AS distroless-base - -# The distroless amd64 image has a target triplet of x86_64 -FROM distroless-base AS distroless-amd64 -ENV LIB_DIR_PREFIX=x86_64 -ENV LIB_DIR_PREFIX_MINUS=x86-64 -ENV LIB_DIR_SUFFIX_NUMBER=2 -ENV LIB_DIR=lib64 - -# The distroless arm64 image has a target triplet of aarch64 -FROM distroless-base AS distroless-arm64 -ENV LIB_DIR_PREFIX=aarch64 -ENV LIB_DIR_PREFIX_MINUS=aarch64 -ENV LIB_DIR_SUFFIX_NUMBER=1 -ENV LIB_DIR=lib +FROM gcr.io/distroless/base-debian11 AS libvirt-provider -FROM busybox:1.37.0-uclibc AS busybox -FROM distroless-$TARGETARCH AS libvirt-provider WORKDIR / COPY --from=busybox /bin/sh /bin/sh -COPY --from=busybox /bin/mkdir /bin/mkdir -COPY --from=builder /lib/${LIB_DIR_PREFIX}-linux-gnu/librados.so.2 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/librbd.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libc.so.6 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libfmt.so.9 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libstdc++.so.6 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libgcc_s.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libssl.so.3 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libcryptsetup.so.12 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libcrypto.so.3 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libresolv.so.2 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libboost_thread.so.1.74.0 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libboost_iostreams.so.1.74.0 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libblkid.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libudev.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libibverbs.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/librdmacm.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libm.so.6 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libuuid.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libdevmapper.so.1.02.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libargon2.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libjson-c.so.5 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libz.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libbz2.so.1.0 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/liblzma.so.5 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libzstd.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libnl-route-3.so.200 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libnl-3.so.200 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libselinux.so.1 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libpthread.so.0 \ -/lib/${LIB_DIR_PREFIX}-linux-gnu/libpcre2-8.so.0 /lib/${LIB_DIR_PREFIX}-linux-gnu/ -RUN mkdir -p /${LIB_DIR} -COPY --from=builder /${LIB_DIR}/ld-linux-${LIB_DIR_PREFIX_MINUS}.so.${LIB_DIR_SUFFIX_NUMBER} /${LIB_DIR}/ -RUN mkdir -p /usr/lib/${LIB_DIR_PREFIX}-linux-gnu/ceph/ -COPY --from=builder /usr/lib/${LIB_DIR_PREFIX}-linux-gnu/ceph/libceph-common.so.2 /usr/lib/${LIB_DIR_PREFIX}-linux-gnu/ceph -COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /workspace/libvirt-provider /libvirt-provider COPY --from=builder /workspace/irictl-machine /irictl-machine diff --git a/api/machine.go b/api/machine.go index a19e1b88..5af26ba9 100644 --- a/api/machine.go +++ b/api/machine.go @@ -84,11 +84,12 @@ type EmptyDiskSpec struct { } type VolumeConnection struct { - Driver string ` json:"driver,omitempty"` - Handle string ` json:"handle,omitempty"` - Attributes map[string]string ` json:"attributes,omitempty"` - SecretData map[string][]byte ` json:"secret_data,omitempty"` - EncryptionData map[string][]byte ` json:"encryption_data,omitempty"` + Driver string ` json:"driver,omitempty"` + Handle string ` json:"handle,omitempty"` + Attributes map[string]string ` json:"attributes,omitempty"` + SecretData map[string][]byte ` json:"secret_data,omitempty"` + EncryptionData map[string][]byte ` json:"encryption_data,omitempty"` + EffectiveStorageBytes int64 ` json:"effective_storage_bytes,omitempty"` } type VolumeState string diff --git a/cmd/libvirt-provider/app/app.go b/cmd/libvirt-provider/app/app.go index 4a947c23..6dee22b2 100644 --- a/cmd/libvirt-provider/app/app.go +++ b/cmd/libvirt-provider/app/app.go @@ -68,7 +68,6 @@ type Options struct { RootDir string PathSupportedMachineClasses string - ResyncIntervalVolumeSize time.Duration EnableHugepages bool @@ -111,7 +110,6 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&o.RootDir, "libvirt-provider-dir", filepath.Join(homeDir, ".libvirt-provider"), "Path to the directory libvirt-provider manages its content at.") fs.StringVar(&o.PathSupportedMachineClasses, "supported-machine-classes", o.PathSupportedMachineClasses, "File containing supported machine classes.") - fs.DurationVar(&o.ResyncIntervalVolumeSize, "volume-size-resync-interval", 1*time.Minute, "Interval to determine volume size changes.") fs.StringVar(&o.StreamingAddress, "streaming-address", ":20251", "Address to run the streaming server on") fs.StringVar(&o.BaseURL, "base-url", "", "The base url to construct urls for streaming from. If empty it will be "+ @@ -314,7 +312,6 @@ func Run(ctx context.Context, opts Options) error { Raw: rawInst, VolumePluginManager: volumePlugins, NetworkInterfacePlugin: nicPlugin, - ResyncIntervalVolumeSize: opts.ResyncIntervalVolumeSize, ResyncIntervalGarbageCollector: opts.ResyncIntervalGarbageCollector, EnableHugepages: opts.EnableHugepages, GCVMGracefulShutdownTimeout: opts.GCVMGracefulShutdownTimeout, diff --git a/go.mod b/go.mod index 40ce245a..666a5a07 100644 --- a/go.mod +++ b/go.mod @@ -6,17 +6,16 @@ toolchain go1.24.1 require ( github.com/blang/semver/v4 v4.0.0 - github.com/ceph/go-ceph v0.33.0 github.com/containerd/containerd v1.7.27 - github.com/digitalocean/go-libvirt v0.0.0-20250417173424-a6a66ef779d6 + github.com/digitalocean/go-libvirt v0.0.0-20250512231903-57024326652b github.com/go-chi/chi/v5 v5.2.1 - github.com/go-logr/logr v1.4.2 + github.com/go-logr/logr v1.4.3 github.com/google/uuid v1.6.0 github.com/ironcore-dev/controller-utils v0.9.9 - github.com/ironcore-dev/ironcore v0.2.3 + github.com/ironcore-dev/ironcore v0.2.4-0.20250605101147-768826bd8776 github.com/ironcore-dev/ironcore-image v0.2.4 github.com/ironcore-dev/ironcore-net v0.2.3 - github.com/ironcore-dev/provider-utils v0.0.0-20250409071032-ef57cc16e3c6 + github.com/ironcore-dev/provider-utils v0.0.0-20250603083958-8628d8f587bc github.com/moby/term v0.5.2 github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.37.0 @@ -25,13 +24,13 @@ require ( github.com/shirou/gopsutil/v3 v3.24.5 github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 - golang.org/x/sync v0.14.0 - google.golang.org/grpc v1.72.1 + golang.org/x/sync v0.15.0 + google.golang.org/grpc v1.73.0 k8s.io/api v0.33.1 k8s.io/apimachinery v0.33.1 k8s.io/client-go v0.33.1 k8s.io/kubectl v0.33.1 - k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e + k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 libvirt.org/go/libvirtxml v1.11004.0 sigs.k8s.io/controller-runtime v0.21.0 ) @@ -113,14 +112,14 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.37.0 // indirect - golang.org/x/net v0.39.0 // indirect + golang.org/x/crypto v0.38.0 // indirect + golang.org/x/net v0.40.0 // indirect golang.org/x/oauth2 v0.29.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/term v0.31.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.32.0 // indirect + golang.org/x/tools v0.33.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250421163800-61c742ae3ef0 // indirect diff --git a/go.sum b/go.sum index f65bb578..d2dde708 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,6 @@ github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuP github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/ceph/go-ceph v0.33.0 h1:xT9v/MAa+DIBmflyITyFkGRgWngATghGegKJguEOInQ= -github.com/ceph/go-ceph v0.33.0/go.mod h1:6ef0lIyDHnwArykqfWZDWCfbbJAVTXL1tOYrM1M4bAE= 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/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= @@ -51,8 +49,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/digitalocean/go-libvirt v0.0.0-20250417173424-a6a66ef779d6 h1:jk2z9emvvDmaTwTdVOvQCK3POtH6+fEvWUtqMBjvnq0= -github.com/digitalocean/go-libvirt v0.0.0-20250417173424-a6a66ef779d6/go.mod h1:vumyuXRJJvjCdabRsu/BvoCirqGHC5bakkC9G0V3Mgw= +github.com/digitalocean/go-libvirt v0.0.0-20250512231903-57024326652b h1:o/RoLbHmKtibc3lMpuPcYGUjnboEORpLFnqtC89tfqY= +github.com/digitalocean/go-libvirt v0.0.0-20250512231903-57024326652b/go.mod h1:B2R8mtJc0BNx0NvvfOajL5no+MaFDumyD5sHsxll62g= github.com/distribution/distribution/v3 v3.0.0-beta.1 h1:X+ELTxPuZ1Xe5MsD3kp2wfGUhc8I+MPfRis8dZ818Ic= 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= @@ -91,8 +89,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= @@ -109,8 +107,6 @@ 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/gofrs/uuid/v5 v5.3.2 h1:2jfO8j3XgSwlz/wHqemAEugfnTlikAYHhnqQ8Xh4fE0= -github.com/gofrs/uuid/v5 v5.3.2/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= 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,14 +149,14 @@ 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.9.9 h1:SRVMjj+jh9yDZj//1hGG7U7S4fRuUVICAiXu7JBHJyo= github.com/ironcore-dev/controller-utils v0.9.9/go.mod h1:hNqQjd6JkRmKYH1MY1XkfT4Eew3P7etHTJjaHj+vK9Y= -github.com/ironcore-dev/ironcore v0.2.3 h1:me2LuScaoekxSRtV7KhCqGZ/jOsU7fCuqt6LBxcx+ts= -github.com/ironcore-dev/ironcore v0.2.3/go.mod h1:u39dlr8d3RfPCK4FLBLvFfmbDdh8Tu7a3R06nXkIJug= +github.com/ironcore-dev/ironcore v0.2.4-0.20250605101147-768826bd8776 h1:pVhUOUcWvFUbHwRpalAXOH0CEzB2yuwsnc1nbvIoiCI= +github.com/ironcore-dev/ironcore v0.2.4-0.20250605101147-768826bd8776/go.mod h1:zGcugDTTLXs9fosZoio+PMpGBY3W0g0PHn4MFD9j1sE= 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-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-20250409071032-ef57cc16e3c6 h1:LOwltmAO/c3YeqG+aRTXUnSto52Ox9FHzNEEMSae8cw= -github.com/ironcore-dev/provider-utils v0.0.0-20250409071032-ef57cc16e3c6/go.mod h1:YJtzgDeOCQqDoUO0pwxczW23lv9dT0x/6SnjLkAPv/I= +github.com/ironcore-dev/provider-utils v0.0.0-20250603083958-8628d8f587bc h1:F03t3hZXmi21V6kjIRRqe+CQcZ3sSRJkX9YQqa04wng= +github.com/ironcore-dev/provider-utils v0.0.0-20250603083958-8628d8f587bc/go.mod h1:eRrTKf37eqHL4ucflPSbskwI/OcgcouYew/byJnIycw= 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/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -340,8 +336,8 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= 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/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -350,8 +346,8 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -359,8 +355,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -372,22 +368,22 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= 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= @@ -398,8 +394,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e h1: google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e/go.mod h1:085qFyf2+XaZlRdCgKNCIZ3afY2p4HHZdoIRpId8F4A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250421163800-61c742ae3ef0 h1:l7lvb5BMqtbmd7fibSq7fi956Fv9/sqiwI9qOw8ltCo= google.golang.org/genproto/googleapis/rpc v0.0.0-20250421163800-61c742ae3ef0/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= -google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= +google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -436,8 +432,8 @@ k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUy k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/kubectl v0.33.1 h1:OJUXa6FV5bap6iRy345ezEjU9dTLxqv1zFTVqmeHb6A= k8s.io/kubectl v0.33.1/go.mod h1:Z07pGqXoP4NgITlPRrnmiM3qnoo1QrK1zjw85Aiz8J0= -k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro= -k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= libvirt.org/go/libvirtxml v1.11004.0 h1:QC/rKw6LhxRHfIrfkHM3P+j5B39sm/+ToDC8J+e8U+I= libvirt.org/go/libvirtxml v1.11004.0/go.mod h1:7Oq2BLDstLr/XtoQD8Fr3mfDNrzlI3utYKySXF2xkng= oras.land/oras-go v1.2.6 h1:z8cmxQXBU8yZ4mkytWqXfo6tZcamPwjsuxYU81xJ8Lk= diff --git a/internal/controllers/machine_controller.go b/internal/controllers/machine_controller.go index fcef52d0..c32228d3 100644 --- a/internal/controllers/machine_controller.go +++ b/internal/controllers/machine_controller.go @@ -73,7 +73,6 @@ type MachineReconcilerOptions struct { VolumePluginManager *providervolume.PluginManager NetworkInterfacePlugin providernetworkinterface.Plugin VolumeEvents event.Source[*api.Machine] - ResyncIntervalVolumeSize time.Duration ResyncIntervalGarbageCollector time.Duration EnableHugepages bool GCVMGracefulShutdownTimeout time.Duration @@ -113,7 +112,6 @@ func NewMachineReconciler( raw: opts.Raw, volumePluginManager: opts.VolumePluginManager, networkInterfacePlugin: opts.NetworkInterfacePlugin, - resyncIntervalVolumeSize: opts.ResyncIntervalVolumeSize, resyncIntervalGarbageCollector: opts.ResyncIntervalGarbageCollector, enableHugepages: opts.EnableHugepages, gcVMGracefulShutdownTimeout: opts.GCVMGracefulShutdownTimeout, @@ -140,8 +138,6 @@ type MachineReconciler struct { machineEvents event.Source[*api.Machine] recorder.EventRecorder - resyncIntervalVolumeSize time.Duration - gcVMGracefulShutdownTimeout time.Duration resyncIntervalGarbageCollector time.Duration @@ -185,12 +181,6 @@ func (r *MachineReconciler) Start(ctx context.Context) error { }() var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - r.startCheckAndEnqueueVolumeResize(ctx, r.log.WithName("volume-size")) - }() - wg.Add(1) go func() { defer wg.Done() @@ -221,60 +211,6 @@ func (r *MachineReconciler) Start(ctx context.Context) error { return nil } -func (r *MachineReconciler) startCheckAndEnqueueVolumeResize(ctx context.Context, log logr.Logger) { - if r.resyncIntervalVolumeSize == 0 { - log.V(1).Info("volume resize trigger loop is disabled") - return - } - - wait.UntilWithContext(ctx, func(ctx context.Context) { - log.V(1).Info("starting volume resize trigger loop") - machines, err := r.machines.List(ctx) - if err != nil { - log.Error(err, "failed to list machines") - return - } - - for _, machine := range machines { - if machine.DeletedAt != nil || !slices.Contains(machine.Finalizers, MachineFinalizer) { - continue - } - - var shouldEnqueue bool - for _, volume := range machine.Spec.Volumes { - plugin, err := r.volumePluginManager.FindPluginBySpec(volume) - if err != nil { - log.Error(err, "failed to get volume plugin", "machineID", machine.ID, "volumeName", volume.Name) - continue - } - - volumeID, err := plugin.GetBackingVolumeID(volume) - if err != nil { - log.Error(err, "failed to get volume id", "machineID", machine.ID, "volumeName", volume.Name) - continue - } - - volumeSize, err := plugin.GetSize(ctx, volume) - if err != nil { - log.Error(err, "failed to get volume size", "machineID", machine.ID, "volumeName", volume.Name, "volumeID", volumeID) - continue - } - - if lastVolumeSize := getLastVolumeSize(machine, GetUniqueVolumeName(plugin.Name(), volumeID)); volumeSize != lastVolumeSize { - r.Eventf(machine.Metadata, corev1.EventTypeNormal, "SizeChangedVolume", "Volume size changed %s, lastVolumeSize: %d bytes, volumeSize: %d bytes", volume.Name, lastVolumeSize, volumeSize) - log.V(1).Info("Volume size changed", "volumeName", volume.Name, "volumeID", volumeID, "machineID", machine.ID, "lastSize", lastVolumeSize, "volumeSize", volumeSize) - shouldEnqueue = true - break - } - } - - if shouldEnqueue { - r.queue.AddRateLimited(machine.ID) - } - } - }, r.resyncIntervalVolumeSize) -} - func (r *MachineReconciler) startEnqueueMachineByLibvirtEvent(ctx context.Context, log logr.Logger) { lifecycleEvents, err := r.host.Libvirt().LifecycleEvents(ctx) if err != nil { diff --git a/internal/controllers/machine_controller_volumes.go b/internal/controllers/machine_controller_volumes.go index 869a73af..a515dd8e 100644 --- a/internal/controllers/machine_controller_volumes.go +++ b/internal/controllers/machine_controller_volumes.go @@ -441,7 +441,7 @@ func (a *libvirtVolumeAttacher) DetachVolume(name string) error { } func (a *libvirtVolumeAttacher) ResizeVolume(volume *AttachVolume) error { - return a.executor.ResizeDisk(volume.Device, volume.Spec.Size) + return a.executor.ResizeDisk(volume.Device, volume.Spec.EffectiveStorageBytesSize) } func (a *libvirtVolumeAttacher) GetVolume(name string) (*AttachVolume, error) { @@ -645,8 +645,8 @@ func (r *MachineReconciler) applyVolume( } //TODO do epsilon comparison - if lastVolumeSize := getLastVolumeSize(machine, volumeID); lastVolumeSize != 0 && providerVolume.Size != lastVolumeSize { - log.V(1).Info("Resize volume", "volumeID", volumeID, "lastSize", lastVolumeSize, "volumeSize", providerVolume.Size) + if lastVolumeSize := getLastVolumeSize(machine, volumeID); lastVolumeSize != 0 && providerVolume.EffectiveStorageBytesSize != lastVolumeSize { + log.V(1).Info("Resize volume", "volumeID", volumeID, "lastSize", lastVolumeSize, "volumeSize", providerVolume.EffectiveStorageBytesSize) if err := attacher.ResizeVolume(&AttachVolume{ Name: desiredVolume.Name, Device: desiredVolume.Device, @@ -656,7 +656,7 @@ func (r *MachineReconciler) applyVolume( } } - return volumeID, providerVolume.Size, nil + return volumeID, providerVolume.EffectiveStorageBytesSize, nil } func (r *MachineReconciler) listDesiredVolumes(machine *api.Machine) map[string]*api.VolumeSpec { diff --git a/internal/mcr/registry.go b/internal/mcr/registry.go index 4cdd143f..b0f27d25 100644 --- a/internal/mcr/registry.go +++ b/internal/mcr/registry.go @@ -17,8 +17,8 @@ import ( "k8s.io/apimachinery/pkg/util/yaml" ) -func LoadMachineClasses(reader io.Reader) ([]iri.MachineClass, error) { - var classList []iri.MachineClass +func LoadMachineClasses(reader io.Reader) ([]*iri.MachineClass, error) { + var classList []*iri.MachineClass if err := yaml.NewYAMLOrJSONDecoder(reader, 4096).Decode(&classList); err != nil { return nil, fmt.Errorf("unable to unmarshal machine classes: %w", err) } @@ -26,7 +26,7 @@ func LoadMachineClasses(reader io.Reader) ([]iri.MachineClass, error) { return classList, nil } -func LoadMachineClassesFile(filename string) ([]iri.MachineClass, error) { +func LoadMachineClassesFile(filename string) ([]*iri.MachineClass, error) { file, err := os.Open(filename) if err != nil { return nil, fmt.Errorf("unable to open machine class file (%s): %w", filename, err) @@ -35,9 +35,9 @@ func LoadMachineClassesFile(filename string) ([]iri.MachineClass, error) { return LoadMachineClasses(file) } -func NewMachineClassRegistry(classes []iri.MachineClass) (*Mcr, error) { +func NewMachineClassRegistry(classes []*iri.MachineClass) (*Mcr, error) { registry := Mcr{ - classes: map[string]iri.MachineClass{}, + classes: map[string]*iri.MachineClass{}, } for _, class := range classes { @@ -51,19 +51,19 @@ func NewMachineClassRegistry(classes []iri.MachineClass) (*Mcr, error) { } type Mcr struct { - classes map[string]iri.MachineClass + classes map[string]*iri.MachineClass } func (m *Mcr) Get(machineClassName string) (*iri.MachineClass, bool) { class, found := m.classes[machineClassName] - return &class, found + return class, found } func (m *Mcr) List() []*iri.MachineClass { var classes []*iri.MachineClass for name := range m.classes { class := m.classes[name] - classes = append(classes, &class) + classes = append(classes, class) } return classes } diff --git a/internal/plugins/volume/ceph/ceph.go b/internal/plugins/volume/ceph/ceph.go index de483061..e86be042 100644 --- a/internal/plugins/volume/ceph/ceph.go +++ b/internal/plugins/volume/ceph/ceph.go @@ -33,12 +33,13 @@ type plugin struct { } type volumeData struct { - monitors []volume.CephMonitor - image string - handle string - userID string - userKey string - encryptionKey *string + monitors []volume.CephMonitor + image string + handle string + userID string + userKey string + encryptionKey *string + effectiveStorageBytes int64 } func NewPlugin() volume.Plugin { @@ -138,11 +139,6 @@ func (p *plugin) Apply(ctx context.Context, spec *api.VolumeSpec, machine *api.M } } - volumeSize, err := p.GetSize(ctx, spec) - if err != nil { - return nil, fmt.Errorf("failed to get volume size: %w", err) - } - return &volume.Volume{ QCow2File: "", RawFile: "", @@ -155,8 +151,8 @@ func (p *plugin) Apply(ctx context.Context, spec *api.VolumeSpec, machine *api.M }, Encryption: cephEncryption, }, - Handle: volumeData.handle, - Size: volumeSize, + Handle: volumeData.handle, + EffectiveStorageBytesSize: volumeData.effectiveStorageBytes, }, nil } @@ -197,6 +193,9 @@ func (p *plugin) getVolumeData(spec *api.VolumeSpec) (vData *volumeData, err err } } + if effectiveStorageBytes := spec.Connection.EffectiveStorageBytes; effectiveStorageBytes != 0 { + vData.effectiveStorageBytes = effectiveStorageBytes + } return vData, nil } diff --git a/internal/plugins/volume/ceph/size.go b/internal/plugins/volume/ceph/size.go deleted file mode 100644 index 211d06e4..00000000 --- a/internal/plugins/volume/ceph/size.go +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors -// SPDX-License-Identifier: Apache-2.0 - -package ceph - -import ( - "context" - "errors" - "fmt" - "os" - "strings" - "time" - - "github.com/ceph/go-ceph/rados" - "github.com/ceph/go-ceph/rbd" - "github.com/go-logr/logr" - "github.com/ironcore-dev/libvirt-provider/api" -) - -func createKeyFile(imageName string, key string) (string, func() error, error) { - noOpCleanup := func() error { return nil } - file, err := os.CreateTemp("", fmt.Sprintf("%s-*", imageName)) - if err != nil { - return "", noOpCleanup, fmt.Errorf("failed to create temp file: %w", err) - } - cleanup := func() error { - return os.Remove(file.Name()) - } - - _, err = file.WriteString(key) - if err != nil { - return "", cleanup, fmt.Errorf("failed to write key to temp file: %w", err) - } - - return file.Name(), cleanup, nil -} - -func connectToRados(ctx context.Context, monitors, user, keyfile string) (*rados.Conn, error) { - args := []string{"-m", monitors, "--keyfile=" + keyfile} - conn, err := rados.NewConnWithUser(user) - if err != nil { - return nil, fmt.Errorf("creating a new connection failed: %w", err) - } - - err = conn.ParseCmdLineArgs(args) - if err != nil { - return nil, fmt.Errorf("parsing cmdline args (%v) failed: %w", args, err) - } - - done := make(chan error, 1) - go func() { - done <- conn.Connect() - }() - - select { - case <-ctx.Done(): - return nil, fmt.Errorf("ceph connect timeout. monitors: %s, user: %s: %w", monitors, user, ctx.Err()) - case err := <-done: - if err != nil { - return nil, fmt.Errorf("connecting failed: %w", err) - } - } - - return conn, nil -} - -func (p *plugin) GetSize(ctx context.Context, spec *api.VolumeSpec) (int64, error) { - log := logr.FromContextOrDiscard(ctx) - - if spec.Connection == nil { - return 0, errors.New("connection data is not set") - } - - userID, userKey, err := readSecretData(spec.Connection.SecretData) - if err != nil { - return 0, fmt.Errorf("error reading secret data: %w", err) - } - - monitors, ok := spec.Connection.Attributes[volumeAttributesMonitorsKey] - if !ok { - return 0, fmt.Errorf("no monitors at %s", volumeAttributesMonitorsKey) - } - - imageHandle, ok := spec.Connection.Attributes[volumeAttributeImageKey] - if !ok { - return 0, fmt.Errorf("no image at %s", volumeAttributeImageKey) - } - - parts := strings.SplitN(imageHandle, "/", 2) - if len(parts) != 2 { - return 0, fmt.Errorf("image handle is not well formated: expected 'pool/image' format but got %s", imageHandle) - } - poolName, imageName := parts[0], parts[1] - - keyFile, cleanup, err := createKeyFile(imageName, userKey) - defer func() { - if err := cleanup(); err != nil { - log.Error(err, "failed to cleanup key file") - } - }() - if err != nil { - return 0, fmt.Errorf("failed to create temp key file: %w", err) - } - - timeoutCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - - conn, err := connectToRados(timeoutCtx, monitors, userID, keyFile) - if err != nil { - return 0, fmt.Errorf("failed to open connection: %w", err) - } - defer conn.Shutdown() - - ioCtx, err := conn.OpenIOContext(poolName) - if err != nil { - return 0, fmt.Errorf("failed to open io context: %w", err) - } - defer ioCtx.Destroy() - - image, err := rbd.OpenImageReadOnly(ioCtx, imageName, rbd.NoSnapshot) - if err != nil { - return 0, fmt.Errorf("failed to open image: %w", err) - } - - size, err := image.GetSize() - if err != nil { - if closeErr := image.Close(); closeErr != nil { - return 0, errors.Join(err, fmt.Errorf("unable to close image: %w", closeErr)) - } - return 0, fmt.Errorf("failed to set encryption format: %w", err) - } - - if err := image.Close(); err != nil { - return 0, fmt.Errorf("failed to close rbd image: %w", err) - } - - return int64(size), nil -} diff --git a/internal/plugins/volume/emptydisk/emptydisk.go b/internal/plugins/volume/emptydisk/emptydisk.go index 6b354b06..f202bc0b 100644 --- a/internal/plugins/volume/emptydisk/emptydisk.go +++ b/internal/plugins/volume/emptydisk/emptydisk.go @@ -91,18 +91,13 @@ func (p *plugin) Apply(ctx context.Context, spec *api.VolumeSpec, machine *api.M return nil, fmt.Errorf("error changing disk file mode: %w", err) } } - return &volume.Volume{RawFile: diskFilename, Handle: handle, Size: size}, nil + return &volume.Volume{RawFile: diskFilename, Handle: handle}, nil } func (p *plugin) Delete(ctx context.Context, computeVolumeName string, machineID string) error { return os.RemoveAll(p.host.MachineVolumeDir(machineID, utilstrings.EscapeQualifiedName(pluginName), computeVolumeName)) } -func (p *plugin) GetSize(ctx context.Context, spec *api.VolumeSpec) (int64, error) { - // Currently Ironcore does not support resize of EmptyDisk - return spec.EmptyDisk.Size, nil -} - // randomHex generates random hexadecimal digits of the length n*2. func randomHex(n int) (string, error) { bytes := make([]byte, n) diff --git a/internal/plugins/volume/plugins.go b/internal/plugins/volume/plugins.go index baa969ae..db74b2eb 100644 --- a/internal/plugins/volume/plugins.go +++ b/internal/plugins/volume/plugins.go @@ -26,16 +26,14 @@ type Plugin interface { Apply(ctx context.Context, spec *api.VolumeSpec, machine *api.Machine) (*Volume, error) Delete(ctx context.Context, computeVolumeName string, machineID string) error - - GetSize(ctx context.Context, spec *api.VolumeSpec) (int64, error) } type Volume struct { - QCow2File string - RawFile string - CephDisk *CephDisk - Handle string - Size int64 + QCow2File string + RawFile string + CephDisk *CephDisk + Handle string + EffectiveStorageBytesSize int64 } type CephDisk struct { diff --git a/internal/server/machine.go b/internal/server/machine.go index fd5649e6..b189e871 100644 --- a/internal/server/machine.go +++ b/internal/server/machine.go @@ -248,11 +248,12 @@ func (s *Server) getVolumeFromIRIVolume(iriVolume *iri.Volume) (*api.VolumeSpec, var connectionSpec *api.VolumeConnection if connection := iriVolume.Connection; connection != nil { connectionSpec = &api.VolumeConnection{ - Driver: connection.Driver, - Handle: connection.Handle, - Attributes: connection.Attributes, - SecretData: connection.SecretData, - EncryptionData: connection.EncryptionData, + Driver: connection.Driver, + Handle: connection.Handle, + Attributes: connection.Attributes, + SecretData: connection.SecretData, + EncryptionData: connection.EncryptionData, + EffectiveStorageBytes: connection.EffectiveStorageBytes, } } diff --git a/internal/server/server.go b/internal/server/server.go index feca5a6b..6f7176ed 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -28,6 +28,8 @@ import ( var _ iri.MachineRuntimeServer = (*Server)(nil) type Server struct { + iri.UnimplementedMachineRuntimeServer + baseURL *url.URL idGen idgen.IDGen diff --git a/internal/server/server_suite_test.go b/internal/server/server_suite_test.go index 5e1825b6..ac1511da 100644 --- a/internal/server/server_suite_test.go +++ b/internal/server/server_suite_test.go @@ -129,7 +129,6 @@ var _ = BeforeSuite(func() { NicPlugin: pluginOpts, GCVMGracefulShutdownTimeout: gracefulShutdownTimeout, ResyncIntervalGarbageCollector: resyncGarbageCollectorInterval, - ResyncIntervalVolumeSize: resyncVolumeSizeInterval, GuestAgent: app.GuestAgentOption(api.GuestAgentNone), MachineEventStore: recorder.EventStoreOptions{ MaxEvents: machineEventMaxEvents, diff --git a/internal/server/status_test.go b/internal/server/status_test.go index a4240ce2..0356aa30 100644 --- a/internal/server/status_test.go +++ b/internal/server/status_test.go @@ -34,7 +34,7 @@ var _ = Describe("Status", func() { MemoryBytes: machineClasses[0].Capabilities.MemoryBytes, }, }, - Quantity: mcr.GetQuantity(&machineClasses[0], hostResources), + Quantity: mcr.GetQuantity(machineClasses[0], hostResources), }, &iriv1alpha1.MachineClassStatus{ MachineClass: &iriv1alpha1.MachineClass{ @@ -44,7 +44,7 @@ var _ = Describe("Status", func() { MemoryBytes: machineClasses[1].Capabilities.MemoryBytes, }, }, - Quantity: mcr.GetQuantity(&machineClasses[1], hostResources), + Quantity: mcr.GetQuantity(machineClasses[1], hostResources), }, )) })