From 9de0efa42fabad0655b2d232b490e8f426f3bab2 Mon Sep 17 00:00:00 2001 From: Freerk-Ole Zakfeld Date: Wed, 14 May 2025 20:28:02 +0200 Subject: [PATCH] Add NEUTRON_ROUTER_EXTERNAL_NETWORK_ID Filter Signed-off-by: Freerk-Ole Zakfeld --- README.md | 4 ++++ exporters/neutron.go | 14 ++++++++------ exporters/neutron_test.go | 4 ++-- main.go | 6 +++++- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index cf64687..0e3f0e9 100644 --- a/README.md +++ b/README.md @@ -52,4 +52,8 @@ DESIGNATE_ENABLED=true MANILA_ENABLED=false NEUTRON_ENABLED=true OCTAVIA_ENABLED=true + +# Routers returned by the Neutron Exporter are filtered by a specific external network ID. +# This is designed to only count the usage of routers which are connected to an external network. +NEUTRON_ROUTER_EXTERNAL_NETWORK_ID=5d8722dd-186c-4e32-a170-b216a04688dc ``` diff --git a/exporters/neutron.go b/exporters/neutron.go index e344b5d..b8f8306 100644 --- a/exporters/neutron.go +++ b/exporters/neutron.go @@ -8,14 +8,16 @@ import ( ) type NeutronUsageExporter struct { - db *sql.DB - floatingIPs *prometheus.Desc - routers *prometheus.Desc + db *sql.DB + externalNetworkId string + floatingIPs *prometheus.Desc + routers *prometheus.Desc } -func NewNeutronUsageExporter(db *sql.DB) (*NeutronUsageExporter, error) { +func NewNeutronUsageExporter(db *sql.DB, externalNetworkId string) (*NeutronUsageExporter, error) { return &NeutronUsageExporter{ - db: db, + db: db, + externalNetworkId: externalNetworkId, floatingIPs: prometheus.NewDesc( "openstack_project_floating_ips", "Total number of floating IPs per OpenStack project", @@ -63,7 +65,7 @@ func (e *NeutronUsageExporter) collectMetrics(ch chan<- prometheus.Metric) { } routerCounts := make(map[string]float64) - rows, err = e.db.Query("SELECT project_id, COUNT(id) AS total_routers FROM routers GROUP BY project_id") + rows, err = e.db.Query("SELECT r.project_id, COUNT(r.id) AS total_routers FROM routers r INNER JOIN ports p ON r.gw_port_id = p.id WHERE p.network_id = ? GROUP BY r.project_id", e.externalNetworkId) if err != nil { log.Println("Error querying router counts:", err) return diff --git a/exporters/neutron_test.go b/exporters/neutron_test.go index f8a3145..6a51368 100644 --- a/exporters/neutron_test.go +++ b/exporters/neutron_test.go @@ -23,9 +23,9 @@ func TestNeutronUsageExporter(t *testing.T) { routerRows := sqlmock.NewRows([]string{"project_id", "total_routers"}). AddRow("c352b0ed-30ca-4634-9c2d-1947efc29096", 1). AddRow("6ee08ba2-2ca1-4c91-b139-4bf0dbaa4096", 2) - mock.ExpectQuery("SELECT project_id, COUNT\\(id\\) AS total_routers FROM routers GROUP BY project_id").WillReturnRows(routerRows) + mock.ExpectQuery("SELECT r.project_id, COUNT\\(r.id\\) AS total_routers FROM routers r").WithArgs("5d8722dd-186c-4e32-a170-b216a04688dc").WillReturnRows(routerRows) - exporter, err := NewNeutronUsageExporter(db) + exporter, err := NewNeutronUsageExporter(db, "5d8722dd-186c-4e32-a170-b216a04688dc") if err != nil { t.Fatalf("Failed to create NeutronUsageExporter: %v", err) } diff --git a/main.go b/main.go index e834263..e3ad72f 100644 --- a/main.go +++ b/main.go @@ -69,7 +69,11 @@ func main() { } exporter, err = exporters.NewNovaTraitUsageExporter(db, trait) case "neutron": - exporter, err = exporters.NewNeutronUsageExporter(db) + externalNetworkId, exists := os.LookupEnv("NEUTRON_ROUTER_EXTERNAL_NETWORK_ID") + if !exists { + log.Fatalf("NEUTRON_ROUTER_EXTERNAL_NETWORK_ID not set") + } + exporter, err = exporters.NewNeutronUsageExporter(db, externalNetworkId) case "designate": exporter, err = exporters.NewDesignateUsageExporter(db) case "octavia":