Skip to content

Commit 8d6bac3

Browse files
committed
Add hypervisorVersion to report running hypervisor version
Calls ConnectGetVersion() to get the hypervisor version (e.g., CH 50.0.0) and reports it in status.HypervisorVersion, separate from libVirtVersion. This complements PR #53 which fixed libVirtVersion to report the actual libvirt library version using ConnectGetLibVersion().
1 parent a01b62e commit 8d6bac3

4 files changed

Lines changed: 154 additions & 56 deletions

File tree

go.mod

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ go 1.25.0
77

88
require (
99
github.com/cert-manager/cert-manager v1.19.3
10-
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260107080351-e998a1af4394
10+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260219130725-f5e32545f7a1
1111
github.com/coreos/go-systemd/v22 v22.6.0
1212
github.com/digitalocean/go-libvirt v0.0.0-20260105165635-a0e369cfdc9f
1313
github.com/godbus/dbus/v5 v5.2.2
14-
github.com/onsi/ginkgo/v2 v2.27.3
15-
github.com/onsi/gomega v1.38.3
16-
github.com/sapcc/go-api-declarations v1.18.0
14+
github.com/onsi/ginkgo/v2 v2.28.1
15+
github.com/onsi/gomega v1.39.1
16+
github.com/sapcc/go-api-declarations v1.19.0
1717
k8s.io/api v0.35.0
1818
k8s.io/apimachinery v0.35.0
1919
k8s.io/client-go v0.35.0
20-
sigs.k8s.io/controller-runtime v0.22.4
20+
sigs.k8s.io/controller-runtime v0.23.1
2121
)
2222

2323
require (
@@ -56,7 +56,7 @@ require (
5656
github.com/google/cel-go v0.26.1 // indirect
5757
github.com/google/gnostic-models v0.7.1 // indirect
5858
github.com/google/go-cmp v0.7.0 // indirect
59-
github.com/google/pprof v0.0.0-20251007162407-5df77e3f7d1d // indirect
59+
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect
6060
github.com/google/uuid v1.6.0 // indirect
6161
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 // indirect
6262
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -86,17 +86,17 @@ require (
8686
go.uber.org/zap v1.27.1 // indirect
8787
go.yaml.in/yaml/v2 v2.4.3 // indirect
8888
go.yaml.in/yaml/v3 v3.0.4 // indirect
89-
golang.org/x/crypto v0.46.0 // indirect
89+
golang.org/x/crypto v0.47.0 // indirect
9090
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 // indirect
91-
golang.org/x/mod v0.31.0 // indirect
92-
golang.org/x/net v0.48.0 // indirect
91+
golang.org/x/mod v0.32.0 // indirect
92+
golang.org/x/net v0.49.0 // indirect
9393
golang.org/x/oauth2 v0.34.0 // indirect
9494
golang.org/x/sync v0.19.0 // indirect
95-
golang.org/x/sys v0.39.0 // indirect
96-
golang.org/x/term v0.38.0 // indirect
97-
golang.org/x/text v0.32.0 // indirect
95+
golang.org/x/sys v0.40.0 // indirect
96+
golang.org/x/term v0.39.0 // indirect
97+
golang.org/x/text v0.33.0 // indirect
9898
golang.org/x/time v0.14.0 // indirect
99-
golang.org/x/tools v0.40.0 // indirect
99+
golang.org/x/tools v0.41.0 // indirect
100100
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
101101
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b // indirect
102102
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect
@@ -114,6 +114,6 @@ require (
114114
sigs.k8s.io/gateway-api v1.4.1 // indirect
115115
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
116116
sigs.k8s.io/randfill v1.0.0 // indirect
117-
sigs.k8s.io/structured-merge-diff/v6 v6.3.1 // indirect
117+
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect
118118
sigs.k8s.io/yaml v1.6.0 // indirect
119119
)

go.sum

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ github.com/cert-manager/cert-manager v1.19.3 h1:3d0Nk/HO3BOmAdBJNaBh+6YgaO3Ciey3
1414
github.com/cert-manager/cert-manager v1.19.3/go.mod h1:e9NzLtOKxTw7y99qLyWGmPo6mrC1Nh0EKKcMkRfK+GE=
1515
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
1616
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
17-
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260107080351-e998a1af4394 h1:GWyHLNTwXp4m+D7OGuQwtIWGRPUBCEjVSowK4CgrdQU=
18-
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260107080351-e998a1af4394/go.mod h1:i/YQm59sAvilkgTFpKc+elMIf/KzkdimnXMd13P3V9s=
17+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260219130725-f5e32545f7a1 h1:BrjR13i+O895T210W/gD/g2p5c0/ZM0a4tDlttPHxTE=
18+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260219130725-f5e32545f7a1/go.mod h1:tp9h2MM6OkufwEiIek9tIndpBar0SiPf8q31KM6MRUg=
1919
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
2020
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
2121
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
@@ -103,8 +103,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
103103
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
104104
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
105105
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
106-
github.com/google/pprof v0.0.0-20251007162407-5df77e3f7d1d h1:KJIErDwbSHjnp/SGzE5ed8Aol7JsKiI5X7yWKAtzhM0=
107-
github.com/google/pprof v0.0.0-20251007162407-5df77e3f7d1d/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U=
106+
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc=
107+
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
108108
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
109109
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
110110
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 h1:kEISI/Gx67NzH3nJxAmY/dGac80kKZgZt134u7Y/k1s=
@@ -135,10 +135,10 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd
135135
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
136136
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
137137
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
138-
github.com/onsi/ginkgo/v2 v2.27.3 h1:ICsZJ8JoYafeXFFlFAG75a7CxMsJHwgKwtO+82SE9L8=
139-
github.com/onsi/ginkgo/v2 v2.27.3/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
140-
github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM=
141-
github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
138+
github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI=
139+
github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
140+
github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=
141+
github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg=
142142
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
143143
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
144144
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -155,8 +155,8 @@ github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05Zp
155155
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
156156
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
157157
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
158-
github.com/sapcc/go-api-declarations v1.18.0 h1:I73wuBKJEAeAI7nYuB4tHY9n9pydj5mgM7Zn+9fryAA=
159-
github.com/sapcc/go-api-declarations v1.18.0/go.mod h1:N2klk2oDNa1lsS6gUBnCDJedHy/c2vmwJ1sryckRW40=
158+
github.com/sapcc/go-api-declarations v1.19.0 h1:AdCHBhoDGC1REMJF6Rc/XLIcf4qMqjUXs5WLq83HImM=
159+
github.com/sapcc/go-api-declarations v1.19.0/go.mod h1:eiRrXXUeQS5C/1kKn8/KMjk0Y0goUzgDQswj30rH0Zc=
160160
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
161161
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
162162
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@@ -215,28 +215,28 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
215215
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
216216
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
217217
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
218-
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
219-
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
218+
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
219+
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
220220
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
221221
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
222-
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
223-
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
224-
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
225-
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
222+
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
223+
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
224+
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
225+
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
226226
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
227227
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
228228
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
229229
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
230-
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
231-
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
232-
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
233-
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
234-
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
235-
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
230+
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
231+
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
232+
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
233+
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
234+
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
235+
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
236236
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
237237
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
238-
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
239-
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
238+
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
239+
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
240240
gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0=
241241
gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
242242
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
@@ -279,15 +279,15 @@ k8s.io/utils v0.0.0-20251222233032-718f0e51e6d2 h1:OfgiEo21hGiwx1oJUU5MpEaeOEg6c
279279
k8s.io/utils v0.0.0-20251222233032-718f0e51e6d2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
280280
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec=
281281
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
282-
sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A=
283-
sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
282+
sigs.k8s.io/controller-runtime v0.23.1 h1:TjJSM80Nf43Mg21+RCy3J70aj/W6KyvDtOlpKf+PupE=
283+
sigs.k8s.io/controller-runtime v0.23.1/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0=
284284
sigs.k8s.io/gateway-api v1.4.1 h1:NPxFutNkKNa8UfLd2CMlEuhIPMQgDQ6DXNKG9sHbJU8=
285285
sigs.k8s.io/gateway-api v1.4.1/go.mod h1:AR5RSqciWP98OPckEjOjh2XJhAe2Na4LHyXD2FUY7Qk=
286286
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
287287
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
288288
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
289289
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
290-
sigs.k8s.io/structured-merge-diff/v6 v6.3.1 h1:JrhdFMqOd/+3ByqlP2I45kTOZmTRLBUm5pvRjeheg7E=
291-
sigs.k8s.io/structured-merge-diff/v6 v6.3.1/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
290+
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8=
291+
sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
292292
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
293293
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=

internal/libvirt/libvirt.go

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ import (
3939
)
4040

4141
type LibVirt struct {
42-
virt *libvirt.Libvirt
43-
client client.Client
44-
migrationJobs map[string]context.CancelFunc
45-
migrationLock sync.Mutex
46-
version string
42+
virt *libvirt.Libvirt
43+
client client.Client
44+
migrationJobs map[string]context.CancelFunc
45+
migrationLock sync.Mutex
46+
version string
47+
hypervisorVersion string
4748

4849
// Event channels for domains by their libvirt event id.
4950
domEventChs map[libvirt.DomainEventID]<-chan any
@@ -81,14 +82,25 @@ func NewLibVirt(k client.Client) *LibVirt {
8182
make(map[string]context.CancelFunc),
8283
sync.Mutex{},
8384
"N/A",
84-
make(map[libvirt.DomainEventID]<-chan any), sync.Mutex{},
85-
make(map[libvirt.DomainEventID]map[string]func(context.Context, any)), sync.Mutex{},
85+
"N/A",
86+
make(map[libvirt.DomainEventID]<-chan any),
87+
sync.Mutex{},
88+
make(map[libvirt.DomainEventID]map[string]func(context.Context, any)),
89+
sync.Mutex{},
8690
capabilities.NewClient(),
8791
domcapabilities.NewClient(),
8892
dominfo.NewClient(),
8993
}
9094
}
9195

96+
// formatLibvirtVersion converts a libvirt version integer to a semver string.
97+
// Libvirt versions are encoded as major*1000000 + minor*1000 + release.
98+
// For example, version 8001002 becomes "8.1.2".
99+
func formatLibvirtVersion(version uint64) string {
100+
major, minor, release := version/1000000, (version/1000)%1000, version%1000
101+
return fmt.Sprintf("%d.%d.%d", major, minor, release)
102+
}
103+
92104
func (l *LibVirt) Connect() error {
93105
// Check if already connected
94106
if l.virt.IsConnected() {
@@ -104,12 +116,18 @@ func (l *LibVirt) Connect() error {
104116
return err
105117
}
106118

107-
// Update the version
119+
// Update the libvirt library version
108120
if version, err := l.virt.ConnectGetLibVersion(); err != nil {
109121
logger.Log.Error(err, "unable to fetch libvirt version")
110122
} else {
111-
major, minor, release := version/1000000, (version/1000)%1000, version%1000
112-
l.version = fmt.Sprintf("%d.%d.%d", major, minor, release)
123+
l.version = formatLibvirtVersion(version)
124+
}
125+
126+
// Update the hypervisor version
127+
if hvVersion, err := l.virt.ConnectGetVersion(); err != nil {
128+
logger.Log.Error(err, "unable to fetch hypervisor version")
129+
} else {
130+
l.hypervisorVersion = formatLibvirtVersion(hvVersion)
113131
}
114132

115133
l.WatchDomainChanges(
@@ -222,7 +240,6 @@ func (l *LibVirt) WatchDomainChanges(
222240
handlerId string,
223241
handler func(context.Context, any),
224242
) {
225-
226243
// Register the handler so that it is called when an event with the provided
227244
// eventId is received.
228245
l.domEventChangeHandlersLock.Lock()
@@ -268,10 +285,11 @@ func (l *LibVirt) Process(hv v1.Hypervisor) (v1.Hypervisor, error) {
268285
return hv, nil
269286
}
270287

271-
// Add the libvirt version to the hypervisor instance.
288+
// Add the libvirt and hypervisor versions to the hypervisor instance.
272289
func (l *LibVirt) addVersion(old v1.Hypervisor) (v1.Hypervisor, error) {
273290
newHv := *old.DeepCopy()
274291
newHv.Status.LibVirtVersion = l.version
292+
newHv.Status.HypervisorVersion = l.hypervisorVersion
275293
return newHv, nil
276294
}
277295

internal/libvirt/libvirt_test.go

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,83 @@ func (m *mockEventloopRunnable) close() {
108108
}
109109
}
110110

111+
func TestFormatLibvirtVersion(t *testing.T) {
112+
tests := []struct {
113+
name string
114+
input uint64
115+
expected string
116+
}{
117+
{
118+
name: "libvirt 8.0.0",
119+
input: 8000000,
120+
expected: "8.0.0",
121+
},
122+
{
123+
name: "libvirt 8.1.2",
124+
input: 8001002,
125+
expected: "8.1.2",
126+
},
127+
{
128+
name: "hypervisor 50.0.0",
129+
input: 50000000,
130+
expected: "50.0.0",
131+
},
132+
{
133+
name: "version with all components",
134+
input: 10009003,
135+
expected: "10.9.3",
136+
},
137+
{
138+
name: "zero version",
139+
input: 0,
140+
expected: "0.0.0",
141+
},
142+
{
143+
name: "large major version",
144+
input: 999000000,
145+
expected: "999.0.0",
146+
},
147+
{
148+
name: "large minor version",
149+
input: 1999000,
150+
expected: "1.999.0",
151+
},
152+
{
153+
name: "large release version",
154+
input: 1000999,
155+
expected: "1.0.999",
156+
},
157+
{
158+
name: "all max components",
159+
input: 999999999,
160+
expected: "999.999.999",
161+
},
162+
{
163+
name: "real world: libvirt 10.0.0",
164+
input: 10000000,
165+
expected: "10.0.0",
166+
},
167+
{
168+
name: "real world: QEMU 8.2.1",
169+
input: 8002001,
170+
expected: "8.2.1",
171+
},
172+
}
173+
174+
for _, tc := range tests {
175+
t.Run(tc.name, func(t *testing.T) {
176+
result := formatLibvirtVersion(tc.input)
177+
if result != tc.expected {
178+
t.Errorf("formatLibvirtVersion(%d) = %s, want %s", tc.input, result, tc.expected)
179+
}
180+
})
181+
}
182+
}
183+
111184
func TestAddVersion(t *testing.T) {
112185
l := &LibVirt{
113-
version: "8.0.0",
186+
version: "8.0.0",
187+
hypervisorVersion: "50.0.0",
114188
}
115189

116190
hv := v1.Hypervisor{}
@@ -123,11 +197,16 @@ func TestAddVersion(t *testing.T) {
123197
if result.Status.LibVirtVersion != "8.0.0" {
124198
t.Errorf("Expected LibVirtVersion '8.0.0', got '%s'", result.Status.LibVirtVersion)
125199
}
200+
201+
if result.Status.HypervisorVersion != "50.0.0" {
202+
t.Errorf("Expected HypervisorVersion '50.0.0', got '%s'", result.Status.HypervisorVersion)
203+
}
126204
}
127205

128206
func TestAddVersion_PreservesOtherFields(t *testing.T) {
129207
l := &LibVirt{
130-
version: "8.0.0",
208+
version: "8.0.0",
209+
hypervisorVersion: "50.0.0",
131210
}
132211

133212
hv := v1.Hypervisor{
@@ -775,6 +854,7 @@ func TestProcess_Success(t *testing.T) {
775854
func TestProcess_PreservesOriginalOnError(t *testing.T) {
776855
l := &LibVirt{
777856
version: "8.0.0",
857+
hypervisorVersion: "50.0.0",
778858
capabilitiesClient: &mockCapabilitiesClient{err: &testError{"capability error"}},
779859
domainCapabilitiesClient: &mockDomCapabilitiesClient{},
780860
domainInfoClient: &mockDomInfoClient{},

0 commit comments

Comments
 (0)