From 6745a7e9ed428ffb04991630bce935cd849c1096 Mon Sep 17 00:00:00 2001 From: Oliver Fesseler Date: Mon, 12 Dec 2016 16:37:42 +0100 Subject: [PATCH 1/4] inceases Version --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0c62199..3a4036f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.1 +0.2.5 From b6dcf6623c6d7e1c9720c08e8148967168bc21ee Mon Sep 17 00:00:00 2001 From: Oliver Fesseler Date: Wed, 14 Dec 2016 15:30:08 +0100 Subject: [PATCH 2/4] changed impl. state in README --- README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 37075a3..edefb25 100644 --- a/README.md +++ b/README.md @@ -79,10 +79,17 @@ with `gluster volume info` this is obsolete | volProfile.cumulativeStatus.totalRead | Count | implemented | | volProfile.cumulativeStatus.totalWrite | Count | implemented | | volProfile.cumulativeStats.fopStats.fop.Name | WRITE, STATFS, FLUSH, OPENDIR, CREATE, LOOKUP, READDIR, FINODELK, ENTRYLK, FXATTROP | pending | -| volProfile.cumulativeStats.fopStats.fop.hits | count | pending | -| volProfile.cumulativeStats.fopStats.fop.avgLatency | Gauge | pending | -| volProfile.cumulativeStats.fopStats.fop.minLatency | Gauge | pending | -| volProfile.cumulativeStats.fopStats.fop.maxLatency | Gauge | pending | +| volProfile.cumulativeStats.fopStats.fop.hits | count | implemented | +| volProfile.cumulativeStats.fopStats.fop.avgLatency | Gauge | implemented | +| volProfile.cumulativeStats.fopStats.fop.minLatency | Gauge | implemented | +| volProfile.cumulativeStats.fopStats.fop.maxLatency | Gauge | implemented | + + +### Command `gluster volume status all detail` +| Name | type | Labels | impl. state | +|------|------|--------|-------------| +| volStatus.volumes.volume[].node[].sizeFree | Gauge | hostname, path, volume | implemented | +| volStatus.volumes.volume[].node[].sizeTotal | Gauge | hostname, path, volume | implemented | ## Similar Projects glusterfs exporter for prometheus written in rust. From bc2a6d3eb8e00b7574ba0f6b0b1e44e8bdb42f74 Mon Sep 17 00:00:00 2001 From: Oliver Fesseler Date: Wed, 14 Dec 2016 15:30:31 +0100 Subject: [PATCH 3/4] added new metrics from volume status metrics on node base gluster_node_size_total_bytes gluster_node_size_free_bytes --- gluster_client.go | 13 ++++ main.go | 33 +++++++++ structs/xmlStructs.go | 44 ++++++++++++ structs/xmlStructs_test.go | 38 ++++++++++ test/gluster_volume_status_all_detail.xml | 86 +++++++++++++++++++++++ 5 files changed, 214 insertions(+) create mode 100644 test/gluster_volume_status_all_detail.xml diff --git a/gluster_client.go b/gluster_client.go index c745788..98fa68e 100644 --- a/gluster_client.go +++ b/gluster_client.go @@ -77,3 +77,16 @@ func ExecVolumeProfileGvInfoCumulative(volumeName string) (structs.VolProfile, e } return volumeProfile.VolProfile, nil } + +// ExecVolumeStatusAllDetail executes "gluster volume status all detail" at the local machine +// returns VolumeStatusXML struct and error +func ExecVolumeStatusAllDetail() (structs.VolumeStatusXML, error) { + args := []string{"volume", "status", "all", "detail"} + bytesBuffer := execGlusterCommand(args...) + volumeStatus, err := structs.VolumeStatusAllDetailXMLUnmarshall(bytesBuffer) + if err != nil { + log.Errorf("Something went wrong while unmarshalling xml: %v", err) + return volumeStatus, err + } + return volumeStatus, nil +} diff --git a/main.go b/main.go index e6bc098..eb1b4c7 100644 --- a/main.go +++ b/main.go @@ -53,6 +53,18 @@ var ( []string{"volume"}, nil, ) + nodeSizeFreeBytes = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "", "node_size_free_bytes"), + "Free bytes reported for each node on each instance. Labels are to distinguish origins", + []string{"hostname", "path", "volume"}, nil, + ) + + nodeSizeTotalBytes = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "", "node_size_total_bytes"), + "Total bytes reported for each node on each instance. Labels are to distinguish origins", + []string{"hostname", "path", "volume"}, nil, + ) + brickCount = prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "brick_count"), "Number of bricks at last query.", @@ -102,6 +114,8 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { ch <- brickDataRead ch <- brickDataWritten ch <- peersConnected + ch <- nodeSizeFreeBytes + ch <- nodeSizeTotalBytes } // Collect collects all the metrics @@ -184,6 +198,25 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { } } } + + // executes gluster status all detail + volumeStatusAll, err := ExecVolumeStatusAllDetail() + if err != nil { + log.Errorf("couldn't parse xml of peer status: %v", err) + } + for _, vol := range volumeStatusAll.VolStatus.Volumes { + for _, node := range vol.Volume.Node { + if node.Status != 1 { + } + ch <- prometheus.MustNewConstMetric( + nodeSizeTotalBytes, prometheus.CounterValue, float64(node.SizeTotal), node.Hostname, node.Path, vol.Volume.VolName, + ) + + ch <- prometheus.MustNewConstMetric( + nodeSizeFreeBytes, prometheus.CounterValue, float64(node.SizeFree), node.Hostname, node.Path, vol.Volume.VolName, + ) + } + } } // ContainsVolume checks a slice if it cpntains a element diff --git a/structs/xmlStructs.go b/structs/xmlStructs.go index 1c2cb88..73de822 100644 --- a/structs/xmlStructs.go +++ b/structs/xmlStructs.go @@ -177,3 +177,47 @@ func VolumeProfileGvInfoCumulativeXMLUnmarshall(cmdOutBuff *bytes.Buffer) (Volum xml.Unmarshal(b, &vol) return vol, nil } + +type VolumeStatusXML struct { + XMLName xml.Name `xml:"cliOutput"` + OpRet int `xml:"opRet"` + OpErrno int `xml:"opErrno"` + OpErrstr string `xml:"opErrstr"` + VolStatus struct { + Volumes []struct { + Volume struct { + VolName string `xml:"volName"` + NodeCount int `xml:"nodeCount"` + Node []struct { + Hostname string `xml:"hostname"` + Path string `xml:"path"` + PeerID string `xml:"peerid"` + Status int `xml:"status"` + Port int `xml:"port"` + Ports struct { + TCP int `xml:"tcp"` + RDMA string `xml:"rdma"` + } `xml:"ports"` + Pid int `xml:"pid"` + SizeTotal uint64 `xml:"sizeTotal"` + SizeFree uint64 `xml:"sizeFree"` + Device string `xml:"device"` + BlockSize int `xml:"blockSize"` + MntOptions string `xml:"mntOptions"` + FsName string `xml:"fsName"` + } `xml:"node"` + } `xml:"volume"` + } `xml:"volumes"` + } `xml:"volStatus"` +} + +func VolumeStatusAllDetailXMLUnmarshall(cmdOutBuff *bytes.Buffer) (VolumeStatusXML, error) { + var vol VolumeStatusXML + b, err := ioutil.ReadAll(cmdOutBuff) + if err != nil { + log.Error(err) + return vol, err + } + xml.Unmarshal(b, &vol) + return vol, nil +} diff --git a/structs/xmlStructs_test.go b/structs/xmlStructs_test.go index 445f918..d417988 100644 --- a/structs/xmlStructs_test.go +++ b/structs/xmlStructs_test.go @@ -87,3 +87,41 @@ func TestPeerStatusXMLUnmarshall(t *testing.T) { t.Log("gluster peer status test was successful.") } + +func TestVolumeStatusAllDetailXMLUnmarshall(t *testing.T) { + testXMLPath := "../test/gluster_volume_status_all_detail.xml" + t.Log("Test xml unmarshal for 'gluster peer status' with file: ", testXMLPath) + dat, err := ioutil.ReadFile(testXMLPath) + if err != nil { + t.Errorf("error reading testxml in Path: %v", testXMLPath) + } + volumeStatus, err := VolumeStatusAllDetailXMLUnmarshall(bytes.NewBuffer(dat)) + if err != nil { + t.Error(err) + } + + if volumeStatus.OpErrno != 0 { + t.Error(volumeStatus.OpErrstr) + } + + for _, vol := range volumeStatus.VolStatus.Volumes { + if vol.Volume.NodeCount != 4 { + t.Errorf("nodecount mismatch %v instead of 4", vol.Volume.NodeCount) + } + + for _, node := range vol.Volume.Node { + if node.BlockSize != 4096 { + t.Errorf("blockSize mismatch %v and 4096 expected", node.BlockSize) + } + + } + + if vol.Volume.Node[0].SizeFree != 19517558784 { + t.Errorf("SizeFree doesn't match 19517558784: %v", vol.Volume.Node[0].SizeFree) + } + + if vol.Volume.Node[0].SizeTotal != 20507914240 { + t.Errorf("SizeFree doesn't match 20507914240: %v", vol.Volume.Node[0].SizeTotal) + } + } +} diff --git a/test/gluster_volume_status_all_detail.xml b/test/gluster_volume_status_all_detail.xml new file mode 100644 index 0000000..4d32dbe --- /dev/null +++ b/test/gluster_volume_status_all_detail.xml @@ -0,0 +1,86 @@ + + + 0 + 0 + + + + + gv_test + 4 + + node1.example.local + /mnt/gluster/gv_test + a049c424-bd82-4436-abd4-ef3fc37c76ba + 1 + 49153 + + 49153 + N/A + + 1342 + 20507914240 + 19517558784 + /dev/loop0 + 4096 + rw,relatime,data=ordered + ext4 + + + node2.example.local + /mnt/gluster/gv_test + f6fa44e7-5139-4f6e-8404-6d2ce7d66231 + 1 + 49153 + + 49153 + N/A + + 1303 + 20507914240 + 19517558784 + /dev/loop0 + 4096 + rw,relatime,data=ordered + ext4 + + + node3.example.local + /mnt/gluster/gv_test + 073c4354-f8eb-4474-95b3-c2bc235ca44d + 1 + 49153 + + 49153 + N/A + + 1284 + 20507914240 + 19517558784 + /dev/loop0 + 4096 + rw,relatime,data=ordered + ext4 + + + node4.example.local + /mnt/gluster/gv_test + 1d5d9c25-211c-4db6-8fd6-274cf3774d88 + 1 + 49153 + + 49153 + N/A + + 1312 + 20507914240 + 19517566976 + /dev/loop0 + 4096 + rw,relatime,data=ordered + ext4 + + + + + \ No newline at end of file From 6842db0aae80d0de2805349b33c9bfbfbdce83d8 Mon Sep 17 00:00:00 2001 From: Oliver Fesseler Date: Wed, 14 Dec 2016 15:49:23 +0100 Subject: [PATCH 4/4] fixed merge conflicts --- structs/xmlStructs_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/structs/xmlStructs_test.go b/structs/xmlStructs_test.go index e128e5b..fad6f2a 100644 --- a/structs/xmlStructs_test.go +++ b/structs/xmlStructs_test.go @@ -123,6 +123,8 @@ func TestVolumeStatusAllDetailXMLUnmarshall(t *testing.T) { if vol.Volume.Node[0].SizeTotal != 20507914240 { t.Errorf("SizeFree doesn't match 20507914240: %v", vol.Volume.Node[0].SizeTotal) } + } +} func TestVolumeProfileGvInfoCumulativeXMLUnmarshall(t *testing.T) { testXMLPath := "../test/gluster_volume_profile_gv_test_info_cumulative.xml"