123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- #!/usr/bin/python3
- # Copyright (C) 2023 Philipp Fromme
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- import argparse
- import pytz
- import re
- import subprocess
- import sys
- from enum import Enum
- from datetime import datetime, timedelta
- class State(Enum):
- OK = 0
- WARNING = 1
- CRITICAL = 2
- UNKNOWN = 3
- def set_state(self, state):
- if state.value > self.value:
- return state
- return self
- def main():
- parser = argparse.ArgumentParser(description="Check for LVM snapshots overdue for deletion")
- parser.add_argument("-w", "--warning", help="Warning threshold, default "
- "604800 seconds (one week)", nargs="?", type=int,
- default=604800)
- parser.add_argument("-c", "--critical", help="Critical threshold, default 1209600 seconds (two weeks)",
- nargs="?", type=int, default=1209600)
- parser.add_argument("-z", "--tz", help="Set timezone, default Europe/Berlin",
- nargs="?", type=str, default='Europe/Berlin')
- parser.add_argument("-r", "--regex", help="Only show LVs with names matching regex, "
- "matches all snapshots by default", nargs='+', default=[None])
- parser.add_argument("-d", "--delete", help="Only show snapshots to be deleted",
- action="store_true")
- args = parser.parse_args()
- if args.critical < args.warning:
- sys.exit(f"Critical seconds {args.critical} is less than warning seconds {args.warning}")
- cmd = ['/sbin/lvs', '-o', 'lv_name,lv_time', '--separator=|', '--noheadings', '-S', 'lv_attr=~[^s.*]']
- snapshots = subprocess.check_output(cmd)
- snapshots = snapshots.decode().strip().split('\n')
- dt_now = datetime.now(pytz.timezone(args.tz))
- state = State.OK
- output = ""
- for line in snapshots:
- if not line:
- continue
- line = line.strip()
- elements = line.split('|')
- lv_name = elements[0]
- for pattern in args.regex:
- if pattern is None:
- break
- regex = re.compile(pattern)
- if regex.match(lv_name):
- break
- else:
- continue
- lv_time = elements[1]
- dt_lv_time = datetime.strptime(lv_time, '%Y-%m-%d %H:%M:%S %z')
- dt_warning = dt_lv_time + timedelta(0,args.warning)
- dt_critical = dt_lv_time + timedelta(0,args.critical)
- if dt_warning > dt_now and args.delete:
- continue
- output = (f"{output}\n"
- f"{lv_name}:\n"
- f" Creation Date: {lv_time}\n"
- f" Deletion Date: {dt_warning}")
- dt_delta = None
- if dt_critical < dt_now:
- state = state.set_state(State.CRITICAL)
- elif dt_warning < dt_now:
- state = state.set_state(State.WARNING)
- else:
- continue
- dt_delta = dt_now - dt_warning
- output = (f"{output}\n"
- f" Deletion Overdue: {dt_delta}")
- if state == State.OK:
- output = ("OK: keine zu loeschenden Snapshots gefunden\n"
- f"{output}")
- elif state == State.WARNING:
- output = ("WARNING: folgende Snapshots muessen geloescht werden!\n"
- f"{output}")
- elif state == State.CRITICAL:
- output = ("CRITICAL: einige Snapshots sind bereits DEUTLICH ueber dem Loeschdatum!\n"
- f"{output}")
- print(output)
- sys.exit(state.value)
- if __name__ == "__main__":
- main()
|