Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 157 lines (136 sloc) 5.61 KB
#!/usr/bin/env python
#
# Copyright 2012-6, 42Lines, Inc.
# Original Author: Jim Browne
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import datetime
import pynagios
from pynagios import Plugin, make_option, Response
import boto
from boto.ec2 import regions
def ts_in_past(timestamp):
'''Return true if an AWS format timestamp is in the past.
Return false if not or it timestamp is unparseable.'''
try:
tstamp = datetime.datetime.strptime(timestamp,
'%Y-%m-%dT%H:%M:%S.%fZ')
except ValueError:
return False
tstamp_delta = datetime.datetime.utcnow() - tstamp
return tstamp_delta.total_seconds() > 0
class VolumeEventsCheck(Plugin):
region = make_option("--region",
help="Region to check (default: us-east-1)",
default=[],
action="append")
allregions = make_option("--all",
help="Check all regions",
action="store_true")
warns = []
criticals = []
infos = []
def check(self):
boto_old = 1
# Boto 2.3.0 and later has volume status code
# Boto < 2.0 missing __version__, hence try/except
try:
from pkg_resources import parse_version
if parse_version(boto.__version__) >= parse_version('2.3.0'):
boto_old = 0
except AttributeError:
pass
if boto_old:
message = "Boto version too old. Need 2.3.0 or later"
return Response(pynagios.UNKNOWN, message)
if not self.options.region:
self.options.region = ["us-east-1"]
if self.options.allregions:
regs = regions()
else:
regs = []
for ropt in self.options.region:
for r in regions():
if r.name == ropt:
regs.append(r)
break
else:
message = "Region %s not found." % ropt
return Response(pynagios.UNKNOWN, message)
for r in regs:
self.regioncheck(r)
wmessages = ", ".join(self.warns)
cmessages = ", ".join(self.criticals)
infos = ", ".join(self.infos)
if len(cmessages):
if len(wmessages):
cmessages += " WARNING: " + wmessages
result = Response(pynagios.CRITICAL, cmessages)
elif len(wmessages):
result = Response(pynagios.WARNING, wmessages)
else:
names = [r.name for r in regs]
result = Response(pynagios.OK, "Checked regions: " +
", ".join(names) + " OK: " + infos)
return result
def regioncheck(self, region):
ec2 = boto.connect_ec2(region=region)
#vfilter = { 'volume-status.status' : 'impaired' }
#stats = ec2.get_all_volume_status(filters=vfilter)
stats = ec2.get_all_volume_status()
for stat in stats:
if self.options.verbosity:
print "id %s status %s" % (stat.id, stat.volume_status)
attachinfo = None
if stat.events or stat.actions:
vstates = ec2.get_all_volumes(volume_ids=[stat.id])
for vol in vstates:
if vol.id == stat.id:
if vol.attachment_state() == 'attached':
adata = vol.attach_data
attachinfo = "(%s %s)" % (adata.instance_id,
adata.device)
break
if self.options.verbosity:
print "id %s attached %s" % (stat.id, attachinfo)
if stat.events:
for event in stat.events:
if self.options.verbosity:
print event
message = stat.id
message += ":%s %s" % (event.type, event.description)
message += " nb %s" % (event.not_before)
message += " na %s" % (event.not_after)
if ts_in_past(event.not_after):
message += " %s" % (attachinfo)
self.infos.append(message)
elif attachinfo:
message += " %s" % (attachinfo)
self.criticals.append(message)
else:
self.warns.append(message)
if stat.actions:
for action in stat.actions:
if self.options.verbosity:
print action
message = stat.id
message += ":%s %s" % (action.type, action.description)
message += " code %s" % (action.code)
if attachinfo:
message += " %s" % (attachinfo)
self.criticals.append(message)
else:
self.warns.append(message)
if __name__ == "__main__":
# Instantiate the plugin, check it, and then exit
VolumeEventsCheck().check().exit()