diff --git a/README.md b/README.md index 8011cee..be6057d 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,10 @@ libvirt_domain_block_stats_write_bytes_total{domain="instance-00000337",target_d libvirt_domain_block_stats_write_requests_total{domain="instance-00000337",target_device="sda"} 2.8434899e+07 libvirt_domain_block_stats_write_time_seconds_total{domain="instance-00000337",target_device="sda"} 530522.437009019 +libvirt_pool_info_allocation_bytes{pool="default"} 5.4276182016e+10 +libvirt_pool_info_available_bytes{pool="default"} 5.1278647296e+10 +libvirt_pool_info_capacity_bytes{pool="default"} 1.05554829312e+11 + libvirt_domain_info_cpu_time_seconds_total{domain="instance-00000337"} 949422.12 libvirt_domain_info_maximum_memory_bytes{domain="instance-00000337"} 8.589934592e+09 libvirt_domain_info_memory_usage_bytes{domain="instance-00000337"} 8.589934592e+09 diff --git a/libvirt_exporter.go b/libvirt_exporter.go index a1f898c..35d2b40 100644 --- a/libvirt_exporter.go +++ b/libvirt_exporter.go @@ -38,6 +38,21 @@ var ( "Whether scraping libvirt's metrics was successful.", nil, nil) + libvirtPoolInfoCapacity = prometheus.NewDesc( + prometheus.BuildFQName("libvirt", "pool_info", "capacity_bytes"), + "Pool capacity, in bytes", + []string{"pool"}, + nil) + libvirtPoolInfoAllocation = prometheus.NewDesc( + prometheus.BuildFQName("libvirt", "pool_info", "allocation_bytes"), + "Pool allocation, in bytes", + []string{"pool"}, + nil) + libvirtPoolInfoAvailable = prometheus.NewDesc( + prometheus.BuildFQName("libvirt", "pool_info", "available_bytes"), + "Pool available, in bytes", + []string{"pool"}, + nil) libvirtVersionsInfoDesc = prometheus.NewDesc( prometheus.BuildFQName("libvirt", "", "versions_info"), "Versions of virtualization components", @@ -948,10 +963,44 @@ func CollectDomain(ch chan<- prometheus.Metric, stat libvirt.DomainStats) error return nil } +// Collect Storage pool stats +func CollectStoragePool(ch chan<- prometheus.Metric, pool libvirt.StoragePool) error { + // Refresh pool + err := pool.Refresh(0) + if err != nil { + return err + } + pool_name, err := pool.GetName() + if err != nil { + return err + } + pool_info, err := pool.GetInfo() + if err != nil { + return err + } + // Send metrics to channel + ch <- prometheus.MustNewConstMetric( + libvirtPoolInfoCapacity, + prometheus.GaugeValue, + float64(pool_info.Capacity), + pool_name) + ch <- prometheus.MustNewConstMetric( + libvirtPoolInfoAllocation, + prometheus.GaugeValue, + float64(pool_info.Allocation), + pool_name) + ch <- prometheus.MustNewConstMetric( + libvirtPoolInfoAvailable, + prometheus.GaugeValue, + float64(pool_info.Available), + pool_name) + return nil +} + // CollectFromLibvirt obtains Prometheus metrics from all domains in a // libvirt setup. func CollectFromLibvirt(ch chan<- prometheus.Metric, uri string) error { - conn, err := libvirt.NewConnectReadOnly(uri) + conn, err := libvirt.NewConnect(uri) if err != nil { return err } @@ -1002,6 +1051,19 @@ func CollectFromLibvirt(ch chan<- prometheus.Metric, uri string) error { log.Printf("Failed to scrape metrics: %s", err) } } + + // Collect pool info + pools, err := conn.ListAllStoragePools(libvirt.CONNECT_LIST_STORAGE_POOLS_ACTIVE) + if err != nil { + return err + } + for _, pool := range pools { + err = CollectStoragePool(ch, pool) + pool.Free() + if err != nil { + return err + } + } return nil } @@ -1048,6 +1110,11 @@ func (e *LibvirtExporter) Describe(ch chan<- *prometheus.Desc) { ch <- libvirtUpDesc ch <- libvirtVersionsInfoDesc + // Pool info + ch <- libvirtPoolInfoCapacity + ch <- libvirtPoolInfoAllocation + ch <- libvirtPoolInfoAvailable + // Domain info ch <- libvirtDomainInfoMetaDesc ch <- libvirtDomainInfoMaxMemBytesDesc