Skip to content

Commit e344b1c

Browse files
Auto-discover additional fields for cortex filtering
1 parent ea18efd commit e344b1c

24 files changed

+3750
-59
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ go 1.25.0
77

88
require (
99
github.com/cert-manager/cert-manager v1.19.2
10-
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251211190118-ddfb1ea3841c
10+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251229115749-52d9308090a6
1111
github.com/coreos/go-systemd/v22 v22.6.0
1212
github.com/digitalocean/go-libvirt v0.0.0-20251202224409-8b0babaf9393
1313
github.com/godbus/dbus/v5 v5.2.0

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
1616
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
1717
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251211190118-ddfb1ea3841c h1:mIMnWtGSQKUWt0O2va45As+FWmqyud9GytZEgw/q51Y=
1818
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251211190118-ddfb1ea3841c/go.mod h1:fBdTD4aqJ7o8QhxS9Hfu20mZYg4nu5RnrK8jestmL9c=
19+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251229101148-5c49ce751841 h1:CQTvuKSm1YnALv5gJP2NkX5/3gz6qludor89PJ1eibw=
20+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251229101148-5c49ce751841/go.mod h1:i/YQm59sAvilkgTFpKc+elMIf/KzkdimnXMd13P3V9s=
21+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251229103057-906a154e6429 h1:1E4S42PyC1fsCJ2kjJ2qu+Ryk2vc7C0D1IInDaZWJGU=
22+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251229103057-906a154e6429/go.mod h1:i/YQm59sAvilkgTFpKc+elMIf/KzkdimnXMd13P3V9s=
23+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251229104931-d99e352a3886 h1:Tqvuis23JJnTJMhtL1zo5dqlV6THlNzsS+IfDzWTsRg=
24+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251229104931-d99e352a3886/go.mod h1:i/YQm59sAvilkgTFpKc+elMIf/KzkdimnXMd13P3V9s=
25+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251229115749-52d9308090a6 h1:yjxe8xMx3T2ZR8Vq9NqH332xoUXFAGhzZu/MLD34j0Q=
26+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20251229115749-52d9308090a6/go.mod h1:i/YQm59sAvilkgTFpKc+elMIf/KzkdimnXMd13P3V9s=
1927
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
2028
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
2129
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=

internal/controller/hypervisor_controller.go

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
kvmv1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1"
2828
"k8s.io/apimachinery/pkg/api/meta"
29+
"k8s.io/apimachinery/pkg/api/resource"
2930
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031
"k8s.io/apimachinery/pkg/runtime"
3132
ctrl "sigs.k8s.io/controller-runtime"
@@ -51,9 +52,11 @@ type HypervisorReconciler struct {
5152
}
5253

5354
const (
54-
OSUpdateType = "OperatingSystemUpdate"
55-
LibVirtType = "LibVirtConnection"
56-
CapabilitiesClientType = "CapabilitiesClientConnection"
55+
OSUpdateType = "OperatingSystemUpdate"
56+
LibVirtType = "LibVirtConnection"
57+
CapabilitiesClientType = "CapabilitiesClientConnection"
58+
DomainInfoClientType = "DomainInfoClientConnection"
59+
DomainCapabilitiesClientType = "DomainCapabilitiesClientConnection"
5760
)
5861

5962
// +kubebuilder:rbac:groups=kvm.cloud.sap,resources=hypervisors,verbs=get;list;watch;update;patch;delete
@@ -190,20 +193,64 @@ func (r *HypervisorReconciler) Reconcile(ctx context.Context, req ctrl.Request)
190193
// Update capabilities status.
191194
if capabilities, err := r.Libvirt.GetCapabilities(); err == nil {
192195
hypervisor.Status.Capabilities = capabilities
196+
hypervisor.Status.Capacity = map[string]resource.Quantity{
197+
"cpu": capabilities.HostCpus,
198+
"memory": capabilities.HostMemory,
199+
}
193200
meta.SetStatusCondition(&hypervisor.Status.Conditions, metav1.Condition{
194201
Type: CapabilitiesClientType,
195202
Status: metav1.ConditionTrue,
196203
Reason: "CapabilitiesClientGetSucceeded",
197204
})
198205
} else {
199206
log.Error(err, "failed to get capabilities")
207+
hypervisor.Status.Capabilities = kvmv1.Capabilities{}
208+
hypervisor.Status.Capacity = nil
200209
meta.SetStatusCondition(&hypervisor.Status.Conditions, metav1.Condition{
201210
Type: CapabilitiesClientType,
202211
Status: metav1.ConditionFalse,
203212
Message: err.Error(),
204213
Reason: "CapabilitiesClientGetFailed",
205214
})
206215
}
216+
217+
// Update the hypervisor allocation.
218+
if allocatedResources, err := r.Libvirt.GetAllocatedResources(); err == nil {
219+
hypervisor.Status.Allocation = allocatedResources
220+
meta.SetStatusCondition(&hypervisor.Status.Conditions, metav1.Condition{
221+
Type: DomainInfoClientType,
222+
Status: metav1.ConditionTrue,
223+
Reason: "DomainInfoClientGetSucceeded",
224+
})
225+
} else {
226+
log.Error(err, "failed to get allocated resources")
227+
hypervisor.Status.Allocation = nil
228+
meta.SetStatusCondition(&hypervisor.Status.Conditions, metav1.Condition{
229+
Type: DomainInfoClientType,
230+
Status: metav1.ConditionFalse,
231+
Message: err.Error(),
232+
Reason: "DomainInfoClientGetFailed",
233+
})
234+
}
235+
236+
// Update the domain capabilities status.
237+
if domainCapabilities, err := r.Libvirt.GetDomainCapabilities(); err == nil {
238+
hypervisor.Status.DomainCapabilities = domainCapabilities
239+
meta.SetStatusCondition(&hypervisor.Status.Conditions, metav1.Condition{
240+
Type: DomainCapabilitiesClientType,
241+
Status: metav1.ConditionTrue,
242+
Reason: "DomainCapabilitiesClientGetSucceeded",
243+
})
244+
} else {
245+
log.Error(err, "failed to get domain capabilities")
246+
hypervisor.Status.DomainCapabilities = kvmv1.DomainCapabilities{}
247+
meta.SetStatusCondition(&hypervisor.Status.Conditions, metav1.Condition{
248+
Type: DomainCapabilitiesClientType,
249+
Status: metav1.ConditionFalse,
250+
Message: err.Error(),
251+
Reason: "DomainCapabilitiesClientGetFailed",
252+
})
253+
}
207254
}
208255

209256
// Reconcile operating system update

internal/controller/hypervisor_controller_test.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,26 @@ var _ = Describe("Hypervisor Controller", func() {
108108
GetNumInstancesFunc: func() int {
109109
return 1
110110
},
111-
GetCapabilitiesFunc: func() (kvmv1.CapabilitiesStatus, error) {
112-
return kvmv1.CapabilitiesStatus{
111+
GetCapabilitiesFunc: func() (kvmv1.Capabilities, error) {
112+
return kvmv1.Capabilities{
113113
HostCpuArch: "x86_64",
114114
HostCpus: *resource.NewQuantity(4, resource.DecimalSI),
115115
HostMemory: *resource.NewQuantity(8192, resource.DecimalSI),
116116
}, nil
117117
},
118+
GetDomainCapabilitiesFunc: func() (kvmv1.DomainCapabilities, error) {
119+
return kvmv1.DomainCapabilities{
120+
Arch: "x86_64",
121+
HypervisorType: "kvm",
122+
SupportedCpuModes: []string{"mode/example", "mode/example/1"},
123+
}, nil
124+
},
125+
GetAllocatedResourcesFunc: func() (map[string]resource.Quantity, error) {
126+
return map[string]resource.Quantity{
127+
"memory": *resource.NewQuantity(4096, resource.BinarySI),
128+
"cpu": *resource.NewQuantity(2, resource.DecimalSI),
129+
}, nil
130+
},
118131
},
119132
Systemd: &systemd.InterfaceMock{
120133
CloseFunc: func() {},
@@ -146,7 +159,7 @@ var _ = Describe("Hypervisor Controller", func() {
146159
Expect(hypervisor.Status.Instances).To(HaveLen(1))
147160
Expect(hypervisor.Status.Instances[0].ID).To(Equal("25e2ea06-f6be-4bac-856d-8c2d0bdbcdee"))
148161

149-
Expect(hypervisor.Status.Conditions).To(HaveLen(3))
162+
Expect(hypervisor.Status.Conditions).To(HaveLen(5))
150163

151164
Expect(hypervisor.Status.Conditions[0].Type).To(Equal("test-unit"))
152165
Expect(hypervisor.Status.Conditions[0].Status).To(Equal(metav1.ConditionTrue))

internal/emulator/libvirt.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ import (
2222

2323
v1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1"
2424
golibvirt "github.com/digitalocean/go-libvirt"
25+
"k8s.io/apimachinery/pkg/api/resource"
2526
logger "sigs.k8s.io/controller-runtime/pkg/log"
2627

2728
"github.com/cobaltcore-dev/kvm-node-agent/internal/libvirt"
2829
"github.com/cobaltcore-dev/kvm-node-agent/internal/libvirt/capabilities"
30+
"github.com/cobaltcore-dev/kvm-node-agent/internal/libvirt/domcapabilities"
2931
)
3032

3133
func NewLibVirtEmulator(ctx context.Context) *libvirt.InterfaceMock {
@@ -55,9 +57,19 @@ func NewLibVirtEmulator(ctx context.Context) *libvirt.InterfaceMock {
5557
log.Info("IsConnectedFunc Func called")
5658
return true
5759
},
58-
GetCapabilitiesFunc: func() (v1.CapabilitiesStatus, error) {
60+
GetCapabilitiesFunc: func() (v1.Capabilities, error) {
5961
return capabilities.NewClientEmulator().Get(nil)
6062
},
63+
GetDomainCapabilitiesFunc: func() (v1.DomainCapabilities, error) {
64+
return domcapabilities.NewClientEmulator().Get(nil)
65+
},
66+
GetAllocatedResourcesFunc: func() (map[string]resource.Quantity, error) {
67+
log.Info("GetAllocatedResourcesFunc Func called")
68+
return map[string]resource.Quantity{
69+
"cpu": resource.MustParse("4"),
70+
"memory": resource.MustParse("8192Mi"),
71+
}, nil
72+
},
6173
}
6274
return mockedInterface
6375
}

internal/libvirt/capabilities/client.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ import (
2525
libvirt "github.com/digitalocean/go-libvirt"
2626
"k8s.io/apimachinery/pkg/api/resource"
2727
"sigs.k8s.io/controller-runtime/pkg/log"
28+
29+
"github.com/cobaltcore-dev/kvm-node-agent/internal/libvirt/util"
2830
)
2931

3032
// Client that returns the capabilities of the host we are mounted on.
3133
type Client interface {
3234
// Return the capabilities status of the host we are mounted on.
33-
Get(virt *libvirt.Libvirt) (v1.CapabilitiesStatus, error)
35+
Get(virt *libvirt.Libvirt) (v1.Capabilities, error)
3436
}
3537

3638
// Implementation of the CapabilitiesClient interface.
@@ -42,16 +44,16 @@ func NewClient() Client {
4244
}
4345

4446
// Return the capabilities of the host we are mounted on.
45-
func (m *client) Get(virt *libvirt.Libvirt) (v1.CapabilitiesStatus, error) {
47+
func (m *client) Get(virt *libvirt.Libvirt) (v1.Capabilities, error) {
4648
capabilitiesXMLBytes, err := virt.Capabilities()
4749
if err != nil {
4850
log.Log.Error(err, "failed to get libvirt capabilities")
49-
return v1.CapabilitiesStatus{}, err
51+
return v1.Capabilities{}, err
5052
}
5153
var capabilities Capabilities
5254
if err := xml.Unmarshal(capabilitiesXMLBytes, &capabilities); err != nil {
5355
log.Log.Error(err, "failed to unmarshal libvirt capabilities")
54-
return v1.CapabilitiesStatus{}, err
56+
return v1.Capabilities{}, err
5557
}
5658
return convert(capabilities)
5759
}
@@ -65,30 +67,30 @@ func NewClientEmulator() Client {
6567
}
6668

6769
// Get the capabilities of the host we are mounted on.
68-
func (c *clientEmulator) Get(virt *libvirt.Libvirt) (v1.CapabilitiesStatus, error) {
70+
func (c *clientEmulator) Get(virt *libvirt.Libvirt) (v1.Capabilities, error) {
6971
var capabilities Capabilities
7072
if err := xml.Unmarshal(exampleXML, &capabilities); err != nil {
7173
log.Log.Error(err, "failed to unmarshal example capabilities")
72-
return v1.CapabilitiesStatus{}, err
74+
return v1.Capabilities{}, err
7375
}
7476
return convert(capabilities)
7577
}
7678

7779
// Convert the libvirt capabilities to the API format.
78-
func convert(in Capabilities) (out v1.CapabilitiesStatus, err error) {
80+
func convert(in Capabilities) (out v1.Capabilities, err error) {
7981
out.HostCpuArch = in.Host.CPU.Arch
8082
// Loop over all numa cells to get the total memory + vcpus.
8183
totalMemory := resource.NewQuantity(0, resource.BinarySI)
8284
totalCpus := resource.NewQuantity(0, resource.DecimalSI)
8385
for _, cell := range in.Host.Topology.CellSpec.Cells {
84-
mem, err := cell.Memory.AsQuantity()
86+
mem, err := util.MemoryToResource(cell.Memory.Value, cell.Memory.Unit)
8587
if err != nil {
86-
return v1.CapabilitiesStatus{}, err
88+
return v1.Capabilities{}, err
8789
}
8890
totalMemory.Add(mem)
8991
cpu := resource.NewQuantity(cell.CPUs.Num, resource.DecimalSI)
9092
if cpu == nil {
91-
return v1.CapabilitiesStatus{},
93+
return v1.Capabilities{},
9294
fmt.Errorf("invalid CPU count for cell %d", cell.ID)
9395
}
9496
totalCpus.Add(*cpu)

internal/libvirt/capabilities/schema.go

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,6 @@ limitations under the License.
1717

1818
package capabilities
1919

20-
import (
21-
"fmt"
22-
23-
"k8s.io/apimachinery/pkg/api/resource"
24-
)
25-
2620
// Capabilities as returned from the libvirt driver capabilities api.
2721
//
2822
// The format is the same as returned when executing `virsh capabilities`. See:
@@ -71,27 +65,6 @@ type CapabilitiesHostTopologyCellMemory struct {
7165
Value int64 `xml:",chardata"`
7266
}
7367

74-
// Get the cell memory as resource.Quantity.
75-
func (c CapabilitiesHostTopologyCellMemory) AsQuantity() (resource.Quantity, error) {
76-
var quantity *resource.Quantity
77-
// Check the unit
78-
switch c.Unit {
79-
case "KiB":
80-
quantity = resource.NewQuantity(c.Value*1024, resource.BinarySI)
81-
case "MiB":
82-
quantity = resource.NewQuantity(c.Value*1024*1024, resource.BinarySI)
83-
case "GiB":
84-
quantity = resource.NewQuantity(c.Value*1024*1024*1024, resource.BinarySI)
85-
case "TiB":
86-
quantity = resource.NewQuantity(c.Value*1024*1024*1024*1024, resource.BinarySI)
87-
}
88-
if quantity == nil {
89-
return resource.Quantity{}, fmt.Errorf("unknown memory unit %s", c.Unit)
90-
}
91-
// Set the value
92-
return *quantity, nil
93-
}
94-
9568
type CapabilitiesHostTopologyCellPages struct {
9669
Unit string `xml:"unit,attr"`
9770
Size int `xml:"size,attr"`

0 commit comments

Comments
 (0)