diff --git a/storage/collector.go b/storage/collector.go index 08de9f8a..6a127f1d 100644 --- a/storage/collector.go +++ b/storage/collector.go @@ -50,7 +50,7 @@ func (*storageCollector) Describe(ch chan<- *prometheus.Desc) { // Collect collects metrics from JunOS func (c *storageCollector) Collect(client *rpc.Client, ch chan<- prometheus.Metric, labelValues []string) error { - var x = MultiRoutingEngineResults{} + var x = RpcReply{} err := client.RunCommandAndParseWithParser("show system storage", func(b []byte) error { return parseXML(b, &x) }) @@ -58,8 +58,8 @@ func (c *storageCollector) Collect(client *rpc.Client, ch chan<- prometheus.Metr return err } - for _, re := range x.Results { - for _, f := range re.Storage.Information.Filesystems { + for _, re := range x.MultiRoutingEngineResults.RoutingEngine { + for _, f := range re.StorageInformation.Filesystems { l := append(labelValues, f.FilesystemName, re.Name, f.MountedOn) ch <- prometheus.MustNewConstMetric(totalBlocksDesc, prometheus.GaugeValue, float64(f.TotalBlocks), l...) @@ -77,21 +77,22 @@ func (c *storageCollector) Collect(client *rpc.Client, ch chan<- prometheus.Metr return nil } -func parseXML(b []byte, res *MultiRoutingEngineResults) error { +func parseXML(b []byte, res *RpcReply) error { if strings.Contains(string(b), "multi-routing-engine-results") { return xml.Unmarshal(b, res) } - si := StorageInformation{} - err := xml.Unmarshal(b, &si) + fi := RpcReplyNoRE{} + + err := xml.Unmarshal(b, &fi) if err != nil { return err } - res.Results = []MultiRoutingEngineItem{ - MultiRoutingEngineItem{ - Name: "", - Storage: si, + res.MultiRoutingEngineResults.RoutingEngine = []RoutingEngine{ + RoutingEngine{ + Name: "N/A", + StorageInformation: fi.StorageInformation, }, } return nil diff --git a/storage/rpc.go b/storage/rpc.go index 60888e53..dc0bea99 100644 --- a/storage/rpc.go +++ b/storage/rpc.go @@ -1,18 +1,23 @@ package storage +import "encoding/xml" + +type RpcReply struct { + XMLName xml.Name `xml:"rpc-reply"` + MultiRoutingEngineResults MultiRoutingEngineResults `xml:"multi-routing-engine-results"` +} + type MultiRoutingEngineResults struct { - Results []MultiRoutingEngineItem `xml:"multi-routing-engine-results"` + RoutingEngine []RoutingEngine `xml:"multi-routing-engine-item"` } -type MultiRoutingEngineItem struct { - Name string `xml:"re-name"` - Storage StorageInformation `xml:"multi-routing-engine-item"` +type RoutingEngine struct { + Name string `xml:"re-name"` + StorageInformation StorageInformation `xml:"system-storage-information"` } type StorageInformation struct { - Information struct { - Filesystems []Filesystem `xml:"filesystem"` - } `xml:"system-storage-information"` + Filesystems []Filesystem `xml:"filesystem"` } type Filesystem struct { @@ -23,3 +28,8 @@ type Filesystem struct { UsedPercent string `xml:"used-percent"` MountedOn string `xml:"mounted-on"` } + +type RpcReplyNoRE struct { + XMLName xml.Name `xml:"rpc-reply"` + StorageInformation StorageInformation `xml:"system-storage-information"` +} diff --git a/storage/rpc_test.go b/storage/rpc_test.go index d3ac4113..69d4a8a9 100644 --- a/storage/rpc_test.go +++ b/storage/rpc_test.go @@ -6,14 +6,8 @@ import ( "github.com/stretchr/testify/assert" ) -func TestParse(t *testing.T) { - tests := []struct { - name string - resp string - }{ - { - name: "no nulti routing engine", - resp: ` +func TestParseMultiREOutput(t *testing.T) { + body := ` fpc0 @@ -26,47 +20,107 @@ func TestParse(t *testing.T) { 65 /.mount + + /dev/sda + 2796512 + 1667792 + 905000 + 6r75 + / + + + + + fpc1 + + + /dev/gpt/junos1 + 2796512 + 1667792 + 905000 + 65 + /.mount + + {master:0} - `, - }, - { - name: "multi routing engine", - resp: ` - - - /dev/gpt/junos - 2796512 - 1667792 - 905000 - 65 - /.mount - # - - - {master:0} - - `, - }, + ` + + rpc := RpcReply{} + err := parseXML([]byte(body), &rpc) + + if err != nil { + t.Fatal(err) } - t.Parallel() + assert.NotEmpty(t, rpc.MultiRoutingEngineResults.RoutingEngine[0].StorageInformation) + + // test first routing engine + assert.Equal(t, "fpc0", rpc.MultiRoutingEngineResults.RoutingEngine[0].Name, "re-name") - for _, test := range tests { - t.Run(test.name, func(te *testing.T) { - rpc := MultiRoutingEngineResults{} - err := parseXML([]byte(test.resp), &rpc) - if err != nil { - te.Fatal(err) - } + f := rpc.MultiRoutingEngineResults.RoutingEngine[0].StorageInformation.Filesystems[1] - if assert.Equal(te, len(rpc.Results), 1, "Engines") { - assert.Equal(te, len(rpc.Results[0].Storage.Information.Filesystems), 1, "Filesystems") - } - }) + assert.Equal(t, "/dev/sda", f.FilesystemName, "filesystem-name") + assert.Equal(t, int64(2796512), f.TotalBlocks, "total-blocks") + assert.Equal(t, int64(1667792), f.UsedBlocks, "used-blocks") + assert.Equal(t, "/", f.MountedOn, "mounted-on") + + // test second routing engine + assert.Equal(t, "fpc1", rpc.MultiRoutingEngineResults.RoutingEngine[1].Name, "re-name") + + f = rpc.MultiRoutingEngineResults.RoutingEngine[1].StorageInformation.Filesystems[0] + + assert.Equal(t, "/dev/gpt/junos1", f.FilesystemName, "filesystem-name") + assert.Equal(t, int64(2796512), f.TotalBlocks, "total-blocks") + assert.Equal(t, int64(1667792), f.UsedBlocks, "used-blocks") + assert.Equal(t, "/.mount", f.MountedOn, "mounted-on") +} + +func TestParseNoMultiREOutput(t *testing.T) { + body := ` + + + /dev/md0.uzip + 43628 + 43628 + 0 + 100 + / + + + /var/log + 44306520 + 23882504 + 16879496 + 59 + /.mount/packages/mnt/jweb-xxx/jail/var/log + + + + {backup} + +` + + rpc := RpcReply{} + err := parseXML([]byte(body), &rpc) + + if err != nil { + t.Fatal(err) } + + assert.NotEmpty(t, rpc.MultiRoutingEngineResults.RoutingEngine[0].StorageInformation) + + assert.Equal(t, "N/A", rpc.MultiRoutingEngineResults.RoutingEngine[0].Name, "re-name") + + f := rpc.MultiRoutingEngineResults.RoutingEngine[0].StorageInformation.Filesystems[1] + + assert.Equal(t, "/var/log", f.FilesystemName, "filesystem-name") + assert.Equal(t, int64(44306520), f.TotalBlocks, "total-blocks") + assert.Equal(t, int64(23882504), f.UsedBlocks, "used-blocks") + assert.Equal(t, " 59", f.UsedPercent, "used-percent") + assert.Equal(t, "/.mount/packages/mnt/jweb-xxx/jail/var/log", f.MountedOn, "mounted-on") }