@@ -41,6 +41,8 @@ const (
4141 // kstatDataString = "7"
4242)
4343
44+ var zfsPoolStatesName = []string {"online" , "degraded" , "faulted" , "offline" , "removed" , "unavail" }
45+
4446func (c * zfsCollector ) openProcFile (path string ) (* os.File , error ) {
4547 file , err := os .Open (procFilePath (path ))
4648 if err != nil {
@@ -97,10 +99,6 @@ func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) error {
9799 return err
98100 }
99101
100- if zpoolObjsetPaths == nil {
101- return nil
102- }
103-
104102 for _ , zpoolPath := range zpoolObjsetPaths {
105103 file , err := os .Open (zpoolPath )
106104 if err != nil {
@@ -117,6 +115,34 @@ func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) error {
117115 return err
118116 }
119117 }
118+
119+ zpoolStatePaths , err := filepath .Glob (procFilePath (filepath .Join (c .linuxProcpathBase , c .linuxZpoolStatePath )))
120+ if err != nil {
121+ return err
122+ }
123+
124+ if zpoolStatePaths == nil {
125+ level .Warn (c .logger ).Log ("msg" , "Not found pool state files" )
126+ }
127+
128+ for _ , zpoolPath := range zpoolStatePaths {
129+ file , err := os .Open (zpoolPath )
130+ if err != nil {
131+ // this file should exist, but there is a race where an exporting pool can remove the files -- ok to ignore
132+ level .Debug (c .logger ).Log ("msg" , "Cannot open file for reading" , "path" , zpoolPath )
133+ return errZFSNotAvailable
134+ }
135+
136+ err = c .parsePoolStateFile (file , zpoolPath , func (poolName string , stateName string , isActive uint64 ) {
137+ ch <- c .constPoolStateMetric (poolName , stateName , isActive )
138+ })
139+
140+ file .Close ()
141+ if err != nil {
142+ return err
143+ }
144+ }
145+
120146 return nil
121147}
122148
@@ -235,3 +261,35 @@ func (c *zfsCollector) parsePoolObjsetFile(reader io.Reader, zpoolPath string, h
235261
236262 return scanner .Err ()
237263}
264+
265+ func (c * zfsCollector ) parsePoolStateFile (reader io.Reader , zpoolPath string , handler func (string , string , uint64 )) error {
266+ scanner := bufio .NewScanner (reader )
267+ scanner .Scan ()
268+
269+ actualStateName , err := scanner .Text (), scanner .Err ()
270+ if err != nil {
271+ return err
272+ }
273+
274+ actualStateName = strings .ToLower (actualStateName )
275+
276+ zpoolPathElements := strings .Split (zpoolPath , "/" )
277+ pathLen := len (zpoolPathElements )
278+ if pathLen < 2 {
279+ return fmt .Errorf ("zpool path did not return at least two elements" )
280+ }
281+
282+ zpoolName := zpoolPathElements [pathLen - 2 ]
283+
284+ for _ , stateName := range zfsPoolStatesName {
285+ isActive := uint64 (0 )
286+
287+ if actualStateName == stateName {
288+ isActive = 1
289+ }
290+
291+ handler (zpoolName , stateName , isActive )
292+ }
293+
294+ return nil
295+ }
0 commit comments