Skip to content

Commit 3ef3208

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 81fc9df commit 3ef3208

2 files changed

Lines changed: 112 additions & 14 deletions

File tree

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)