Skip to content

Commit 6645f8a

Browse files
authored
Merge pull request #54 from cobaltcore-dev/feature/report-hypervisor-version
Add hypervisorVersion to report running hypervisor version
2 parents 56cf2f1 + 3ef3208 commit 6645f8a

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)