Skip to content

Commit

Permalink
Loadbalancer (#81)
Browse files Browse the repository at this point in the history
* Implement loadbalancer metrics

* Add loadbalancer_loadbalancers.json to fixtures

* Add metrics total_amphorae and amphora_status to loadbalancer exporter.

* Add loadbalancer_amphorae.json to fixtures

Co-authored-by: Jorge Niedbalski <[email protected]>
  • Loading branch information
tzmtl and niedbalski committed Feb 24, 2020
1 parent f3c8143 commit d431ae6
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 1 deletion.
7 changes: 7 additions & 0 deletions exporters/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ func NewExporter(name, prefix, cloud string, disabledMetrics []string, endpointT
return nil, err
}
}
case "load-balancer":
{
exporter, err = NewLoadbalancerExporter(client, prefix, disabledMetrics)
if err != nil {
return nil, err
}
}
default:
{
return nil, fmt.Errorf("couldn't find a handler for %s exporter", name)
Expand Down
48 changes: 48 additions & 0 deletions exporters/fixtures/loadbalancer_amphorae.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"amphorae": [
{
"id": "6bd55cd3-802e-447e-a518-1e74e23bb106",
"load_balancer_id": "09eedfc6-2c55-41a8-a75c-2cd4e95212ca",
"compute_id": "f0f79f90-733d-417a-8d70-cc6be62cd54d",
"lb_network_ip": "192.168.1.2",
"vrrp_ip": "192.168.1.5",
"ha_ip": "192.168.1.10",
"vrrp_port_id": "ab2a8add-76a9-44bb-89f8-88430193cc83",
"ha_port_id": "19561fd3-5da5-46cc-bdd3-99bbdf7246e6",
"cert_expiration": "2019-09-19 00:34:51",
"cert_busy": 0,
"role": "MASTER",
"status": "ALLOCATED",
"vrrp_interface": "eth1",
"vrrp_id": 1,
"vrrp_priority": 100,
"cached_zone": "zone1",
"created_at": "2017-05-10T18:14:44",
"updated_at": "2017-05-10T23:08:12",
"image_id": "c1c2ad6f-1c1e-4744-8d1a-d0ef36289e74",
"compute_flavor": "5446a14a-abec-4455-bc0e-a34e5ff001a3"
},
{
"id": "89c186a3-cb16-497b-b099-c4bd40316642",
"load_balancer_id": "09eedfc6-2c55-41a8-a75c-2cd4e95212ca",
"compute_id": "24b1cb54-122d-4960-9035-083642f5c2bb",
"lb_network_ip": "192.168.1.3",
"vrrp_ip": "192.168.1.6",
"ha_ip": "192.168.1.10",
"vrrp_port_id": "cae421f6-dcf0-4866-9438-d0c682645799",
"ha_port_id": "19561fd3-5da5-46cc-bdd3-99bbdf7246e6",
"cert_expiration": "2019-09-19 00:34:51",
"cert_busy": 0,
"role": "BACKUP",
"status": "ALLOCATED",
"vrrp_interface": "eth1",
"vrrp_id": 1,
"vrrp_priority": 200,
"cached_zone": "zone2",
"created_at": "2017-06-11T19:15:45",
"updated_at": "2017-06-11T24:09:13",
"image_id": "1014292d-cbaa-4ad6-b38b-2e138389f87f",
"compute_flavor": "5446a14a-abec-4455-bc0e-a34e5ff001a3"
}
]
}
33 changes: 33 additions & 0 deletions exporters/fixtures/loadbalancer_loadbalancers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"loadbalancers": [
{
"description": "My favorite load balancer",
"admin_state_up": true,
"project_id": "e3cd678b11784734bc366148aa37580e",
"provisioning_status": "ACTIVE",
"flavor_id": "",
"vip_subnet_id": "d4af86e1-0051-488c-b7a0-527f97490c9a",
"listeners": [
{
"id": "023f2e34-7806-443b-bfae-16c324569a3d"
}
],
"vip_address": "203.0.113.50",
"vip_network_id": "d0d217df-3958-4fbf-a3c2-8dad2908c709",
"vip_port_id": "b4ca07d1-a31e-43e2-891a-7d14f419f342",
"provider": "octavia",
"pools": [
{
"id": "9aa16cdc-8d18-47b9-aba9-ec044531a79f"
}
],
"created_at": "2017-02-28T00:41:44",
"updated_at": "2017-02-28T00:43:30",
"id": "607226db-27ef-4d41-ae89-f2a800e9c2db",
"operating_status": "ONLINE",
"name": "best_load_balancer",
"vip_qos_policy_id": "ec4f78ca-8da8-4e99-8a1a-e3b94595a7a3",
"tags": []
}
]
}
116 changes: 116 additions & 0 deletions exporters/loadbalancer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package exporters

import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/amphorae"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers"
"github.com/prometheus/client_golang/prometheus"
)

var loadbalancer_status = []string{
// Octavia API v2 entities have two status codes present in the response body.
// The provisioning_status describes the lifecycle status of the entity while the operating_status provides the observed status of the entity.
// Here we put operating_status in metrics value and provisioning_status in metrics label
"ONLINE", // Entity is operating normally. All pool members are healthy
"DRAINING", // The member is not accepting new connections
"OFFLINE", // Entity is administratively disabled
"ERROR", // The entity has failed. The member is failing it's health monitoring checks. All of the pool members are in ERROR
"NO_MONITOR", // No health monitor is configured for this entity and it's status is unknown
}

var amphora_status = []string{
// The status of the amphora. One of: BOOTING, ALLOCATED, READY, PENDING_CREATE, PENDING_DELETE, DELETED, ERROR.
"BOOTING",
"ALLOCATED",
"READY",
"PENDING_CREATE",
"PENDING_DELETE",
"DELETED",
"ERROR",
}

func mapLoadbalancerStatus(current string) int {
for idx, status := range loadbalancer_status {
if current == status {
return idx
}
}
return -1
}

func mapAmphoraStatus(current string) int {
for idx, status := range amphora_status {
if current == status {
return idx
}
}
return -1
}

type LoadbalancerExporter struct {
BaseOpenStackExporter
}

var defaultLoadbalancerMetrics = []Metric{
{Name: "total_loadbalancers", Fn: ListAllLoadbalancers},
{Name: "loadbalancer_status", Labels: []string{"id", "name", "project_id", "operating_status", "provisioning_status", "provider", "vip_address"}},
{Name: "total_amphorae", Fn: ListAllAmphorae},
{Name: "amphora_status", Labels: []string{"id", "loadbalancer_id", "compute_id", "status", "role", "lb_network_ip", "ha_ip"}},
}

func NewLoadbalancerExporter(client *gophercloud.ServiceClient, prefix string, disabledMetrics []string) (*LoadbalancerExporter, error) {
exporter := LoadbalancerExporter{
BaseOpenStackExporter{
Name: "loadbalancer",
Prefix: prefix,
Client: client,
DisabledMetrics: disabledMetrics,
},
}
for _, metric := range defaultLoadbalancerMetrics {
exporter.AddMetric(metric.Name, metric.Fn, metric.Labels, nil)
}
return &exporter, nil
}

func ListAllLoadbalancers(exporter *BaseOpenStackExporter, ch chan<- prometheus.Metric) error {
var allLoadbalancers []loadbalancers.LoadBalancer
allPagesLoadbalancers, err := loadbalancers.List(exporter.Client, loadbalancers.ListOpts{}).AllPages()
if err != nil {
return err
}
allLoadbalancers, err = loadbalancers.ExtractLoadBalancers(allPagesLoadbalancers)
if err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(exporter.Metrics["total_loadbalancers"].Metric,
prometheus.GaugeValue, float64(len(allLoadbalancers)))
// Loadbalancer status metrics
for _, loadbalancer := range allLoadbalancers {
ch <- prometheus.MustNewConstMetric(exporter.Metrics["loadbalancer_status"].Metric,
prometheus.GaugeValue, float64(mapLoadbalancerStatus(loadbalancer.OperatingStatus)), loadbalancer.ID, loadbalancer.Name, loadbalancer.ProjectID,
loadbalancer.OperatingStatus, loadbalancer.ProvisioningStatus, loadbalancer.Provider, loadbalancer.VipAddress)
}
return nil
}

func ListAllAmphorae(exporter *BaseOpenStackExporter, ch chan<- prometheus.Metric) error {
var allAmphorae []amphorae.Amphora
allPagesAmphorae, err := amphorae.List(exporter.Client, amphorae.ListOpts{}).AllPages()
if err != nil {
return err
}
allAmphorae, err = amphorae.ExtractAmphorae(allPagesAmphorae)
if err != nil {
return err
}
ch <- prometheus.MustNewConstMetric(exporter.Metrics["total_amphorae"].Metric,
prometheus.GaugeValue, float64(len(allAmphorae)))
// Loadbalancer status metrics
for _, amphora := range allAmphorae {
ch <- prometheus.MustNewConstMetric(exporter.Metrics["amphora_status"].Metric,
prometheus.GaugeValue, float64(mapAmphoraStatus(amphora.Status)), amphora.ID, amphora.LoadbalancerID, amphora.ComputeID, amphora.Status,
amphora.Role, amphora.LBNetworkIP, amphora.HAIP)
}
return nil
}
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"os"
)

var defaultEnabledServices = []string{"network", "compute", "image", "volume", "identity", "object-store"}
var defaultEnabledServices = []string{"network", "compute", "image", "volume", "identity", "object-store", "load-balancer"}
var DEFAULT_OS_CLIENT_CONFIG = "/etc/openstack/clouds.yaml"

func main() {
Expand Down

0 comments on commit d431ae6

Please sign in to comment.