From 00c9a88a5504a013896f8297c1e11b5c2fefad4b Mon Sep 17 00:00:00 2001 From: dan mcweeney Date: Tue, 20 Sep 2016 10:22:34 -0400 Subject: [PATCH 1/4] Fixes #219 - use the default to catch personalities that are unknown Assumes all raid configurations start with raid and that anything else is unknown. --- collector/fixtures/proc/mdstat | 11 +++++++---- collector/mdadm_linux.go | 33 +++++++++++++++++++++++++++++---- collector/mdadm_linux_test.go | 1 + 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/collector/fixtures/proc/mdstat b/collector/fixtures/proc/mdstat index 5a397fce..c552424a 100644 --- a/collector/fixtures/proc/mdstat +++ b/collector/fixtures/proc/mdstat @@ -1,13 +1,13 @@ Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] md3 : active raid6 sda1[8] sdh1[7] sdg1[6] sdf1[5] sde1[11] sdd1[3] sdc1[10] sdb1[9] 5853468288 blocks super 1.2 level 6, 64k chunk, algorithm 2 [8/8] [UUUUUUUU] - + md127 : active raid1 sdi2[0] sdj2[1] 312319552 blocks [2/2] [UU] - + md0 : active raid1 sdi1[0] sdj1[1] 248896 blocks [2/2] [UU] - + md4 : inactive raid1 sda3[0] sdb3[1] 4883648 blocks [2/2] [UU] @@ -18,7 +18,7 @@ md6 : active raid1 sdb2[2] sda2[0] md8 : active raid1 sdb1[1] sda1[0] 195310144 blocks [2/2] [UU] [=>...................] resync = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec - + md7 : active raid6 sdb1[0] sde1[3] sdd1[2] sdc1[1] 7813735424 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/3] [U_UU] bitmap: 0/30 pages [0KB], 65536KB chunk @@ -37,4 +37,7 @@ md11 : active (auto-read-only) raid1 sdb2[0] sdc2[1] md12 : active raid0 sdc2[0] sdd2[1] 3886394368 blocks super 1.2 512k chunks +md219 : inactive sdb[2](S) sdc[1](S) sda[0](S) + 7932 blocks super external:imsm + unused devices: diff --git a/collector/mdadm_linux.go b/collector/mdadm_linux.go index 61d9ebdb..8ea2ad9a 100644 --- a/collector/mdadm_linux.go +++ b/collector/mdadm_linux.go @@ -31,6 +31,8 @@ var ( statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) raid0lineRE = regexp.MustCompile(`(\d+) blocks .*\d+k chunks`) buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`) + unknownPersonalityLine = regexp.MustCompile(`(\d+) blocks (.*)`) + raidPersonalityRE = regexp.MustCompile(`raid[0-9]+`) ) type mdStatus struct { @@ -92,6 +94,21 @@ func evalRaid0line(statusline string) (size int64, err error) { return size, nil } +func evalUnknownPersonalityline(statusline string) (size int64, err error) { + matches := unknownPersonalityLine.FindStringSubmatch(statusline) + + if len(matches) != 2+1 { + return 0, fmt.Errorf("invalid unknown personality status line: %s", statusline) + } + + size, err = strconv.ParseInt(matches[1], 10, 64) + if err != nil { + return 0, fmt.Errorf("%s in statusline: %s", err, statusline) + } + + return size, nil +} + // Gets the size that has already been synced out of the sync-line. func evalBuildline(buildline string) (int64, error) { matches := buildlineRE.FindStringSubmatch(buildline) @@ -158,19 +175,27 @@ func parseMdstat(mdStatusFilePath string) ([]mdStatus, error) { } currentMD = mainLine[0] // The name of the md-device. isActive := (mainLine[2] == "active") // The activity status of the md-device. - personality = mainLine[3] // The personality type of the md-device. + personality = "" + for _, possiblePersonality := range mainLine { + if raidPersonalityRE.MatchString(possiblePersonality) { + personality = possiblePersonality + } + } if len(lines) <= i+3 { return mdStates, fmt.Errorf("error parsing mdstat: entry for %s has fewer lines than expected", currentMD) } - switch personality { - case "raid0": + switch { + case personality == "raid0": active = int64(len(mainLine) - 4) // Get the number of devices from the main line. total = active // Raid0 active and total is always the same if active. size, err = evalRaid0line(lines[i+1]) // Parse statusline, always present. - default: + case raidPersonalityRE.MatchString(personality): active, total, size, err = evalStatusline(lines[i+1]) // Parse statusline, always present. + default: + log.Infof("Personality unknown: %s\n", mainLine) + size, err = evalUnknownPersonalityline(lines[i+1]) // Parse statusline, always present. } if err != nil { diff --git a/collector/mdadm_linux_test.go b/collector/mdadm_linux_test.go index 89456042..042b9ecd 100644 --- a/collector/mdadm_linux_test.go +++ b/collector/mdadm_linux_test.go @@ -36,6 +36,7 @@ func TestMdadm(t *testing.T) { "md10": {"md10", true, 2, 2, 314159265, 314159265}, "md11": {"md11", true, 2, 2, 4190208, 4190208}, "md12": {"md12", true, 2, 2, 3886394368, 3886394368}, + "md219": {"md219", false, 2, 2, 7932, 7932}, } for _, md := range mdStates { From 8d756cab503fb4a5d99a811ccca50132f6ef293b Mon Sep 17 00:00:00 2001 From: dan mcweeney Date: Tue, 20 Sep 2016 13:39:05 -0400 Subject: [PATCH 2/4] Fixes end to end test --- collector/fixtures/e2e-output.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index 4288a10c..68b8ca37 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt @@ -717,6 +717,7 @@ node_md_blocks{device="md10"} 3.14159265e+08 node_md_blocks{device="md11"} 4.190208e+06 node_md_blocks{device="md12"} 3.886394368e+09 node_md_blocks{device="md127"} 3.12319552e+08 +node_md_blocks{device="md219"} 7932 node_md_blocks{device="md3"} 5.853468288e+09 node_md_blocks{device="md4"} 4.883648e+06 node_md_blocks{device="md6"} 1.95310144e+08 @@ -730,6 +731,7 @@ node_md_blocks_synced{device="md10"} 3.14159265e+08 node_md_blocks_synced{device="md11"} 4.190208e+06 node_md_blocks_synced{device="md12"} 3.886394368e+09 node_md_blocks_synced{device="md127"} 3.12319552e+08 +node_md_blocks_synced{device="md219"} 7932 node_md_blocks_synced{device="md3"} 5.853468288e+09 node_md_blocks_synced{device="md4"} 4.883648e+06 node_md_blocks_synced{device="md6"} 1.6775552e+07 @@ -743,6 +745,7 @@ node_md_disks{device="md10"} 2 node_md_disks{device="md11"} 2 node_md_disks{device="md12"} 2 node_md_disks{device="md127"} 2 +node_md_disks{device="md219"} 2 node_md_disks{device="md3"} 8 node_md_disks{device="md4"} 2 node_md_disks{device="md6"} 2 @@ -756,6 +759,7 @@ node_md_disks_active{device="md10"} 2 node_md_disks_active{device="md11"} 2 node_md_disks_active{device="md12"} 2 node_md_disks_active{device="md127"} 2 +node_md_disks_active{device="md219"} 2 node_md_disks_active{device="md3"} 8 node_md_disks_active{device="md4"} 2 node_md_disks_active{device="md6"} 1 @@ -769,6 +773,7 @@ node_md_is_active{device="md10"} 1 node_md_is_active{device="md11"} 1 node_md_is_active{device="md12"} 1 node_md_is_active{device="md127"} 1 +node_md_is_active{device="md219"} 0 node_md_is_active{device="md3"} 1 node_md_is_active{device="md4"} 0 node_md_is_active{device="md6"} 1 From 1f6b5aee3980a4dad5e557645a50de1810459a0d Mon Sep 17 00:00:00 2001 From: dan mcweeney Date: Tue, 15 Nov 2016 11:36:56 -0500 Subject: [PATCH 3/4] #219 - add fixes for @samzhang111 super token --- collector/fixtures/e2e-output.txt | 5 +++++ collector/fixtures/proc/mdstat | 3 +++ collector/mdadm_linux.go | 9 +++++---- collector/mdadm_linux_test.go | 2 ++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index 68b8ca37..d3bfc6c1 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt @@ -713,6 +713,7 @@ node_load5 0.37 # HELP node_md_blocks Total number of blocks on device. # TYPE node_md_blocks gauge node_md_blocks{device="md0"} 248896 +node_md_blocks{device="md00"} 4.186624e+06 node_md_blocks{device="md10"} 3.14159265e+08 node_md_blocks{device="md11"} 4.190208e+06 node_md_blocks{device="md12"} 3.886394368e+09 @@ -727,6 +728,7 @@ node_md_blocks{device="md9"} 523968 # HELP node_md_blocks_synced Number of blocks synced on device. # TYPE node_md_blocks_synced gauge node_md_blocks_synced{device="md0"} 248896 +node_md_blocks_synced{device="md00"} 4.186624e+06 node_md_blocks_synced{device="md10"} 3.14159265e+08 node_md_blocks_synced{device="md11"} 4.190208e+06 node_md_blocks_synced{device="md12"} 3.886394368e+09 @@ -741,6 +743,7 @@ node_md_blocks_synced{device="md9"} 523968 # HELP node_md_disks Total number of disks of device. # TYPE node_md_disks gauge node_md_disks{device="md0"} 2 +node_md_disks{device="md00"} 1 node_md_disks{device="md10"} 2 node_md_disks{device="md11"} 2 node_md_disks{device="md12"} 2 @@ -755,6 +758,7 @@ node_md_disks{device="md9"} 4 # HELP node_md_disks_active Number of active disks of device. # TYPE node_md_disks_active gauge node_md_disks_active{device="md0"} 2 +node_md_disks_active{device="md00"} 1 node_md_disks_active{device="md10"} 2 node_md_disks_active{device="md11"} 2 node_md_disks_active{device="md12"} 2 @@ -769,6 +773,7 @@ node_md_disks_active{device="md9"} 4 # HELP node_md_is_active Indicator whether the md-device is active or not. # TYPE node_md_is_active gauge node_md_is_active{device="md0"} 1 +node_md_is_active{device="md00"} 1 node_md_is_active{device="md10"} 1 node_md_is_active{device="md11"} 1 node_md_is_active{device="md12"} 1 diff --git a/collector/fixtures/proc/mdstat b/collector/fixtures/proc/mdstat index c552424a..393b3fc9 100644 --- a/collector/fixtures/proc/mdstat +++ b/collector/fixtures/proc/mdstat @@ -40,4 +40,7 @@ md12 : active raid0 sdc2[0] sdd2[1] md219 : inactive sdb[2](S) sdc[1](S) sda[0](S) 7932 blocks super external:imsm +md00 : active raid0 xvdb[0] + 4186624 blocks super 1.2 256k chunks + unused devices: diff --git a/collector/mdadm_linux.go b/collector/mdadm_linux.go index 8ea2ad9a..425b3f75 100644 --- a/collector/mdadm_linux.go +++ b/collector/mdadm_linux.go @@ -28,9 +28,9 @@ import ( ) var ( - statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) - raid0lineRE = regexp.MustCompile(`(\d+) blocks .*\d+k chunks`) - buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`) + statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) + raid0lineRE = regexp.MustCompile(`(\d+) blocks( super ([0-9\.])*)? \d+k chunks`) + buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`) unknownPersonalityLine = regexp.MustCompile(`(\d+) blocks (.*)`) raidPersonalityRE = regexp.MustCompile(`raid[0-9]+`) ) @@ -82,7 +82,7 @@ func evalStatusline(statusline string) (active, total, size int64, err error) { func evalRaid0line(statusline string) (size int64, err error) { matches := raid0lineRE.FindStringSubmatch(statusline) - if len(matches) != 2 { + if len(matches) < 2 { return 0, fmt.Errorf("invalid raid0 status line: %s", statusline) } @@ -179,6 +179,7 @@ func parseMdstat(mdStatusFilePath string) ([]mdStatus, error) { for _, possiblePersonality := range mainLine { if raidPersonalityRE.MatchString(possiblePersonality) { personality = possiblePersonality + // break } } diff --git a/collector/mdadm_linux_test.go b/collector/mdadm_linux_test.go index 042b9ecd..0e4e89ee 100644 --- a/collector/mdadm_linux_test.go +++ b/collector/mdadm_linux_test.go @@ -25,6 +25,7 @@ func TestMdadm(t *testing.T) { } refs := map[string]mdStatus{ + // { "", , , , , } "md3": {"md3", true, 8, 8, 5853468288, 5853468288}, "md127": {"md127", true, 2, 2, 312319552, 312319552}, "md0": {"md0", true, 2, 2, 248896, 248896}, @@ -37,6 +38,7 @@ func TestMdadm(t *testing.T) { "md11": {"md11", true, 2, 2, 4190208, 4190208}, "md12": {"md12", true, 2, 2, 3886394368, 3886394368}, "md219": {"md219", false, 2, 2, 7932, 7932}, + "md00": {"md00", true, 1, 1, 4186624, 4186624}, } for _, md := range mdStates { From 13aa37025f6df2bc385ad5f2b2e7801d221f2a7a Mon Sep 17 00:00:00 2001 From: dan mcweeney Date: Thu, 17 Nov 2016 10:23:01 -0500 Subject: [PATCH 4/4] Feedback on PR, thanks @tcolgate for the review --- collector/mdadm_linux.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/collector/mdadm_linux.go b/collector/mdadm_linux.go index 425b3f75..f820d2b3 100644 --- a/collector/mdadm_linux.go +++ b/collector/mdadm_linux.go @@ -28,11 +28,11 @@ import ( ) var ( - statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) - raid0lineRE = regexp.MustCompile(`(\d+) blocks( super ([0-9\.])*)? \d+k chunks`) - buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`) - unknownPersonalityLine = regexp.MustCompile(`(\d+) blocks (.*)`) - raidPersonalityRE = regexp.MustCompile(`raid[0-9]+`) + statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) + raid0lineRE = regexp.MustCompile(`(\d+) blocks( super ([0-9\.])*)? \d+k chunks`) + buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`) + unknownPersonalityLineRE = regexp.MustCompile(`(\d+) blocks (.*)`) + raidPersonalityRE = regexp.MustCompile(`raid[0-9]+`) ) type mdStatus struct { @@ -94,8 +94,8 @@ func evalRaid0line(statusline string) (size int64, err error) { return size, nil } -func evalUnknownPersonalityline(statusline string) (size int64, err error) { - matches := unknownPersonalityLine.FindStringSubmatch(statusline) +func evalUnknownPersonalitylineRE(statusline string) (size int64, err error) { + matches := unknownPersonalityLineRE.FindStringSubmatch(statusline) if len(matches) != 2+1 { return 0, fmt.Errorf("invalid unknown personality status line: %s", statusline) @@ -176,10 +176,10 @@ func parseMdstat(mdStatusFilePath string) ([]mdStatus, error) { currentMD = mainLine[0] // The name of the md-device. isActive := (mainLine[2] == "active") // The activity status of the md-device. personality = "" - for _, possiblePersonality := range mainLine { + for _, possiblePersonality := range mainLine[3:] { if raidPersonalityRE.MatchString(possiblePersonality) { personality = possiblePersonality - // break + break } } @@ -196,7 +196,7 @@ func parseMdstat(mdStatusFilePath string) ([]mdStatus, error) { active, total, size, err = evalStatusline(lines[i+1]) // Parse statusline, always present. default: log.Infof("Personality unknown: %s\n", mainLine) - size, err = evalUnknownPersonalityline(lines[i+1]) // Parse statusline, always present. + size, err = evalUnknownPersonalitylineRE(lines[i+1]) // Parse statusline, always present. } if err != nil {