2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
10 # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
27 # Agent output and things to know:
29 # hd5 boot 1 2 2 closed/syncd N/A
30 # hd6 paging 65 130 2 open/syncd N/A
31 # hd8 jfs2log 1 2 2 open/syncd N/A
32 # hd4 jfs2 1 2 2 open/syncd /
33 # hd2 jfs2 5 10 2 open/syncd /usr
34 # hd9var jfs2 3 6 2 open/syncd /var
35 # hd3 jfs2 2 4 2 open/syncd /tmp
36 # hd1 jfs2 1 2 2 open/syncd /home
37 # hd10opt jfs2 3 6 2 open/syncd /opt
38 # hd11admin jfs2 1 2 2 open/syncd /admin
39 # lg_dumplv sysdump 6 6 1 open/syncd N/A
40 # livedump jfs2 1 2 2 open/syncd /var/adm/ras/livedump
41 # lvwork jfs2 1 2 2 open/syncd /work
42 # lvbackup jfs2 200 200 1 open/syncd /backup
43 # fwdump jfs2 5 5 1 open/syncd /var/adm/ras/platform
44 # lvoracle jfs2 30 30 1 open/syncd /oracle
46 # hd5 which contains the boot kernel is normally always closed (but it doesn't
47 # matter IF it's closed.
49 # row3: 1 means it alloceted one lvm logical extent (called partition on AIX), so
50 # it's likely 256MB in size.
51 # row4: 2 means it uses two physical extents. So if it uses two physical for
52 # one logical ... yeah, a mirror
54 # row5: 2 means that the volume uses two physical volumes to store those
55 # extents. So the mirror isn't on the same disk if it dies.
57 # row6: here open/syncd is OK for every active volume
61 # hd5 : ("boot", 1, 2, 2, "closed/syncd", None)
62 # hd4 : ("/", 1, 2, 2, "open/syncd", "/")
67 def parse_aix_lvm(info
):
72 lvmconf
.update({vgname
: {}})
73 # Some versions send a title line "LV NAME ..."
74 elif line
[0] == "LV" and line
[1] == "NAME":
77 lv
, lvtype
, num_lp
, num_pp
, num_pv
, act_state
, mountpoint
= line
78 # split lv state into two relevant values
79 activation
, mirror
= act_state
.split("/")
80 if mountpoint
== "N/A":
82 lvmconf
[vgname
].update({
83 lv
: (lvtype
, int(num_lp
), int(num_pp
), int(num_pv
), activation
, mirror
, mountpoint
)
88 def inventory_aix_lvm(info
):
90 for vg
, volumes
in parse_aix_lvm(info
).iteritems():
92 #inventory.append(("%s/%s" % (vg, lv), ('%s' % volumes[lv][4],)))
93 inventory
.append(("%s/%s" % (vg
, lv
), None))
97 def check_aix_lvm(item
, _no_params
, info
):
99 # Get ready to find our item and settings.
100 #target_activation = params
101 target_vg
, target_lv
= item
.split("/")
103 # Get structured LVM info
104 lvmconf
= parse_aix_lvm(info
)
106 if target_vg
in lvmconf
and target_lv
in lvmconf
[target_vg
]:
110 lvtype
, num_lp
, num_pp
, num_pv
, activation
, mirror
, _mountpoint
= lvmconf
[target_vg
][
113 # Test if the volume is mirrored.
114 # Yes? Test for an even distribution of PP's over volumes.
115 # This is cannot detect crossover misaligns and other bad practices.
116 if num_pp
/ num_lp
> 1:
117 if not num_pp
/ num_pv
== num_lp
:
118 msgtxt
.append("LV Mirrors are misaligned between physical volumes(!)")
119 state
= max(state
, 1)
121 # If it's not the boot volume I suspect it should be open.
122 # This may need to be changed for some scenarios
124 if activation
!= "open": # and activation != target_activation:
125 msgtxt
.append("LV is not opened(!)")
126 state
= max(state
, 1)
128 # Detect any, not just mirrored, volumes, that have stale PPs.
129 # This means either a disk write failure causing a mirror to go stale
130 # or some kind of split mirror backup.
131 if mirror
!= "syncd":
133 msgtxt
.append("LV is not in sync state(!!)")
134 state
= max(state
, 2)
137 msgtxt
= "LV is open/syncd"
139 msgtxt
= ", ".join(msgtxt
)
140 return (state
, msgtxt
)
142 return (3, "no such volume found")
145 check_info
['aix_lvm'] = {
146 "check_function": check_aix_lvm
,
147 "inventory_function": inventory_aix_lvm
,
148 "service_description": "Logical Volume %s",
150 # "default_levels_variable" : "services_default_levels",
151 # first check we have a vendor mib from W&T, then check for the model in their MIB.