root/lib/Core/ZpoolFree.pm

Revision c3d87d4cfed0d62d1df83e9ca20b17a56fb30ccc, 3.5 kB (checked in by Mark Harrison <mark@omniti.com>, 4 years ago)

Fix for when snapshots are present

The method used has also changed to use zpool list then zfs list on individual
filesystems. This is because zfs list can be very slow if there are a lot
of filesystems present.

git-svn-id: https://labs.omniti.com/resmon/branches/resmon2@338 8c0face9-b7db-6ec6-c4b3-d5f7145c7d55

  • Property mode set to 100644
Line 
1 package Core::ZpoolFree;
2
3 use strict;
4 use warnings;
5
6 use base 'Resmon::Module';
7
8 use Resmon::ExtComm qw(run_command);
9
10 =pod
11
12 =head1 NAME
13
14 Core::ZpoolFree - monitor free space available on ZFS pools
15
16 =head1 SYNOPSIS
17
18  Core::ZpoolFree {
19      zpools: noop
20  }
21
22  Core::ZpoolFree {
23      zpools: zfs_path = '/sbin/zfs'
24  }
25
26 =head1 DESCRIPTION
27
28 This module monitors the free space on ZFS pools. Free space is reported for
29 all pools on the system. Multiple checks are not required for individual
30 pools.
31
32 Implementation Note: The 'zfs list' command is used rather than 'zpool list'
33 in order to get a more accurate view of the available space in certain cases
34 where zpool list does not report the true usable free space (e.g. raidz
35 pools). See http://www.cuddletech.com/blog/pivot/entry.php?id=1013 for another
36 case where zpool list does not report the correct values for monitoring.
37
38 Zpool list is still used to get the list of pools on the system, and then zfs
39 list is run individually for each pool. This is done to improve performance in
40 the case where there are many filesystems.
41
42 =head1 CONFIGURATION
43
44 =over
45
46 =item check_name
47
48 The check name is descriptive only in this check. It is not used for anything.
49
50 =item zfs_path
51
52 Specify an alternative location for the zfs command. Default: /sbin/zfs.
53
54 =item zpool_path
55
56 Specify an alternative location for the zpool command. Default: /sbin/zpool.
57
58 =back
59
60 =head1 METRICS
61
62 A set of metrics is returned for each pool on the system, with the name of the
63 pool being used as a prefix. For example, if you have rpool and data pools,
64 then you will end up with both rpool_free_KB and data_free_KB (as well as the
65 rest of the metrics for each pool).
66
67 =over
68
69 =item poolname_free_MB
70
71 The amount of free space in the pool, measured in megabytes.
72
73 =item poolname_used_MB
74
75 The amount of used space in the pool, measured in megabytes.
76
77 =item poolname_percent_full
78
79 The amount of used space in the pool, expressed as a percentage of the total
80 space.
81
82 =back
83
84 =cut
85
86 our %units = (
87     'B' => 1,
88     'K' => 1024,
89     'M' => 1048576,
90     'G' => 1073741824,
91     'T' => 1099511627776,
92     'P' => 1125899906842624,
93     'E' => 1152921504606846976,
94     'Z' => 1180591620717411303424
95 );
96
97 sub handler {
98     my $self = shift;
99     my $config = $self->{config}; # All configuration is in here
100     my $zfs_command = $config->{zfs_command} || "/sbin/zfs";
101     my $zpool_command = $config->{zpool_command} || "/sbin/zpool";
102     my $status = {};
103     my $output = run_command("$zpool_command list -H -o name");
104     foreach my $pool (split /\n/, $output) {
105         # Sanity check in case zpool outputs something strange
106         die "Invalid pool name: $pool" if $pool !~ /[a-zA-Z0-9_.-]+/;
107         my $zfs_output = run_command(
108             "$zfs_command list -H -o name,used,avail $pool");
109         my ($name, $used, $uunit, $free, $funit) = $zfs_output =~
110             /(\S+)\s+([0-9.]+)([BKMGTPEZ]?)\s+([0-9.]+)([BKMGTPEZ]?)/;
111         # Make sure we were able to match the regex
112         die "Unable to parse zfs command output: $zfs_output\n"
113             unless defined($name);
114         next if ($name =~ /\//); # We're only interested in the root of a pool
115
116         # Convert human readable units to bytes
117         $used = $used * $units{$uunit} if $uunit;
118         $free = $free * $units{$funit} if $funit;
119
120         my $percent_full = sprintf("%.2f", ($used / ($used + $free)) * 100);
121         $status->{"${name}_used_MB"} = [int($used/1048576), "i"];
122         $status->{"${name}_free_MB"} = [int($free/1048576), "i"];
123         $status->{"${name}_percent_full"} = [$percent_full, "n"];
124     }
125
126     return $status;
127 };
128
129 1;
Note: See TracBrowser for help on using the browser.