Skip to content
This repository has been archived by the owner on Oct 3, 2020. It is now read-only.

Commit

Permalink
Release 0.3.3
Browse files Browse the repository at this point in the history
- VM snapshots are now created before scheduling downtimes, downtime
default timeframe changed to 4 hours (see issue #35)
- vlog behavior altered to be more intelligent (for details see issue
#36))
- Implemented function for scheduling downtime for Nagios/Icinga
hostgroups (see issue #37) [parameters -g / --downtime-hostgroup,
satprep_prepare_maintenance.py]
- Some minor fixes
  • Loading branch information
stdevel committed May 20, 2015
1 parent d01c6b9 commit afea9e4
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 21 deletions.
2 changes: 1 addition & 1 deletion satprep_install_custominfos.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def parse_options(args=None):
If you're not defining variables or an authfile you will be prompted to enter your login information.
Checkout the GitHub page for updates: https://github.com/stdevel/satprep'''
parser = OptionParser(description=desc, version="%prog version 0.3")
parser = OptionParser(description=desc, version="%prog version 0.3.3")
#define option groups
genOpts = OptionGroup(parser, "Generic Options")
srvOpts = OptionGroup(parser, "Server Options")
Expand Down
63 changes: 46 additions & 17 deletions satprep_prepare_maintenance.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import sys
from optparse import OptionParser, OptionGroup
import csv
from satprep_shared import schedule_downtime, get_credentials, create_snapshot, is_downtime, has_snapshot
from satprep_shared import schedule_downtime, get_credentials, create_snapshot, is_downtime, has_snapshot, schedule_downtime_hostgroup
import time
import os
from fnmatch import fnmatch
Expand Down Expand Up @@ -56,14 +56,17 @@ def verify():
#check whether the output directory/file is writable
if os.access(os.getcwd(), os.W_OK):
LOGGER.debug("Output file/directory writable!")
myLog = open(myPrefix+"_satprep.vlog", "w")
myLog = open(myPrefix+"_satprep.vlog", "r+")
#myFile = myLog.readlines()
myFile = myLog.read().splitlines()
LOGGER.debug("vlog before customization: ***\n" + str(myFile))
else:
#directory not writable
LOGGER.error("Output directory NOT writable!")
sys.exit(1)

#check downtimes
if len(downtimeHosts) == 0: LOGGER.info("No downtimes to schedule.")
if len(downtimeHosts) == 0 or options.skipMonitoring: LOGGER.info("No downtimes to verify.")
else:
#check _all_ the downtimes
for host in downtimeHosts:
Expand All @@ -90,17 +93,22 @@ def verify():
if result:
#host in downtime
LOGGER.debug("Host '" + thisHost + "' in downtime. :)")
myLog.write("MONOK;" + thisHost + "\n")
#correct or append entry
if "MONCRIT;"+thisHost in myFile and "MONOK;"+thisHost not in myFile: myFile = [h.replace("MONCRIT;"+thisHost, "MONOK;"+thisHost) for h in myFile]
elif "MONOK;"+thisHost not in myFile: myFile.append("MONOK;"+thisHost)
else:
#host NOT in downtime
LOGGER.error("Host '" + thisHost + "' NOT in downtime. :(")
myLog.write("MONCRIT;" + thisHost + "\n")
#correct or append entry
if "MONOK;"+thisHost in myFile and "MONCRIT;"+thisHost not in myFile: myFile = [h.replace("MONOK;"+thisHost, "MONCRIT;"+thisHost) for h in myFile]
elif "MONCRIT;"+thisHost not in myFile: myFile.append("MONCRIT;"+thisHost)

#check snapshots
if len(snapshotHosts) == 0: LOGGER.info("No snapshots to create.")
if len(snapshotHosts) == 0 or options.skipSnapshot: LOGGER.info("No snapshots to verify.")
else:
#check _all_ the snapshots
for host in snapshotHosts:
LOGGER.debug("Checking snapshot for host '" + host + "'...")
#try to get differing host/credentials
if "@" in host and ":" in host:
thisURI = host[host.find("@")+1:host.rfind(":")]
Expand All @@ -124,12 +132,20 @@ def verify():
if result:
#snapshot exists
LOGGER.debug("Snapshot for VM '" + thisHost + "' found. :)")
myLog.write("SNAPOK;" + thisHost + "\n")
#correct or append entry
if "SNAPCRIT;"+thisHost in myFile and "SNAPOK;"+thisHost not in myFile: myFile = [h.replace("SNAPCRIT;"+thisHost, "SNAPOK;"+thisHost) for h in myFile]
elif "SNAPOK;"+thisHost not in myFile: myFile.append("SNAPOK;"+thisHost)
else:
#snapshot non-existent
LOGGER.error("No snapshot for VM '" + thisHost + "' found. :(")
myLog.write("SNAPCRIT;" + thisHost + "\n")
#close log file
#correct or append entry
if "SNAPOK;"+thisHost in myFile and "SNAPCRIT;"+thisHost not in myFile: myFile = [h.replace("SNAPOK;"+thisHost, "SNAPCRIT;"+thisHost) for h in myFile]
elif "SNAPCRIT;"+thisHost not in myFile: myFile.append("SNAPCRIT;"+thisHost)
#write vlog file
myLog.seek(0)
LOGGER.debug("File after customization: ***\n" + str(myFile))
for line in myFile:
myLog.write(line + "\n")
myLog.close()


Expand All @@ -144,6 +160,21 @@ def setDowntimes():
LOGGER.info("No downtimes to schedule, going home!")
return False

#schedule downtimes for hostgroups if given
if len(options.downtimeHostgroups) != 0 and options.tidy == False:
if options.dryrun:
#simulation
for thisHostgroup in options.downtimeHostgroups:
LOGGER.info("I'd like to schedule downtime for hostgroup '" + thisHostgroup + "'...")
else:
#schedule _all_ the downtimes
for thisHostgroup in options.downtimeHostgroups:
LOGGER.info("Scheduling downtime for hostgroup '" + thisHostgroup + "'...")
#get default login if not specified
if defaultMonUser == "": (defaultMonUser, defaultMonPass) = get_credentials("Monitoring", options.monAuthfile)
result = schedule_downtime_hostgroup(options.URL, defaultMonUser, defaultMonPass, thisHostgroup, options.hours, options.comment, options.userAgent, options.noAuth)
return True

#set downtime for affected hosts
for host in downtimeHosts:
#try to get differing host/credentials
Expand Down Expand Up @@ -179,10 +210,6 @@ def setDowntimes():
else: output = output + "'..."
LOGGER.info(output)

#setup headers
if len(options.userAgent) > 0: myHeaders = {'User-Agent': options.userAgent}
else: myHeaders = {'User-Agent': 'satprep Toolkit (https://github.com/stdevel/satprep)'}

#(un)schedule downtime
if thisURI != "" and thisCred != "":
#get username and password
Expand Down Expand Up @@ -361,9 +388,9 @@ def main(options):
#verify only
verify()
else:
#schedule downtimes and create snapshots
if options.skipMonitoring == False: setDowntimes()
#create snapshots and schedule downtimes
if options.skipSnapshot == False: createSnapshots()
if options.skipMonitoring == False: setDowntimes()
#also verify
if options.dryrun == False:
LOGGER.info("Verifying preparation...")
Expand All @@ -387,7 +414,7 @@ def parse_options(args=None):
Check-out the GitHub documentation (https://github.com/stdevel/satprep) for further information.
'''
parser = OptionParser(usage=usage, description=desc, version="%prog version 0.3")
parser = OptionParser(usage=usage, description=desc, version="%prog version 0.3.3")
#define option groups
genOpts = OptionGroup(parser, "Generic Options")
monOpts = OptionGroup(parser, "Monitoring Options")
Expand Down Expand Up @@ -428,11 +455,13 @@ def parse_options(args=None):
#-u / --monitoring-url
monOpts.add_option("-u", "--monitoring-url", dest="URL", metavar="URL", default="http://localhost/icinga", help="defines the default Nagios/Icinga/Thruk/Shinken URL to use, might be overwritten by custom system keys (default: http://localhost/icinga)")
#-t / --hours
monOpts.add_option("-t", "--hours", action="store", dest="hours", default="2", metavar="HOURS", help="sets the time period in hours hosts should be scheduled for downtime (default: 2)")
monOpts.add_option("-t", "--hours", action="store", dest="hours", default="4", metavar="HOURS", help="sets the time period in hours hosts should be scheduled for downtime (default: 4)")
#-x / --no-auth
monOpts.add_option("-x", "--no-auth", action="store_true", default=False, dest="noAuth", help="disables HTTP basic auth (default: no)")
#-A / --user-agent
monOpts.add_option("-A", "--user-agent", action="store", default="", metavar="AGENT", dest="userAgent", help="sets a custom HTTP user agent")
#-g / --downtime-hostgroup
monOpts.add_option("-g", "--downtime-hostgroup", action="append", type="string", default=[], metavar="HOSTGROUP", dest="downtimeHostgroups", help="defines hostgroups which should be scheduled for downtime. NOTE: This disables scheduling downtime for particular hosts.")

#VM OPTIONS
#-K / --skip-snapshot
Expand Down
43 changes: 42 additions & 1 deletion satprep_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def schedule_downtime(url, monUsername, monPassword, host, hours, comment, agent

#check whether request was successful
if r.status_code != 200:
LOGGER.error("Got HTTP status code " + str(r.status_code) + " instead of 200 while scheduling downtime for host '" + host + "'. Check URL and logon credentials!")
LOGGER.error("Got HTTP status code " + str(r.status_code) + " instead of 200 while (un)scheduling downtime for host '" + host + "'. Check URL and logon credentials!")
return False
else:
if "error" in r.text.lower(): LOGGER.error("Unable to (un)schedule downtime for host '" + host + "' - please run again with -d / --debug and check HTML output! (does this host exist?!)")
Expand All @@ -180,6 +180,47 @@ def schedule_downtime(url, monUsername, monPassword, host, hours, comment, agent



def schedule_downtime_hostgroup(url, monUsername, monPassword, hostgroup, hours, comment, agent="", noAuth=False):
#schedule downtime for hostgroup
#setup headers
if len(agent) > 0: myHeaders = {'User-Agent': agent}
else: myHeaders = {'User-Agent': 'satprep Toolkit (https://github.com/stdevel/satprep)'}
LOGGER.debug("Setting headers: {0}".format(myHeaders))

#setup start and end time for downtime
current_time=time.strftime("%Y-%m-%d %H:%M:%S")
end_time=format(datetime.now() + timedelta(hours=int(hours)), '%Y-%m-%d %H:%M:%S')
LOGGER.debug("current_time: {0}".format(current_time))
LOGGER.debug("end_time: {0}".format(end_time))

#setup payload
#NOTE: there is no way to unschedule downtimes for all hosts/services in a hostgroup
payload = {'cmd_typ': '85', 'cmd_mod': '2', 'hostgroup': hostgroup, 'com_data': comment, 'trigger': '0', 'fixed': '1', 'hours': hours, 'minutes': '0', 'start_time': current_time, 'end_time': end_time, 'btnSubmit': 'Commit', 'com_author': monUsername, 'childoptions': '0', 'ahas': 'on'}
LOGGER.debug("payload: {0}".format(payload))

#setup HTTP session
s = requests.Session()
if noAuth == False: s.auth = HTTPBasicAuth(monUsername, monPassword)

#send POST request
r = s.post(url+"/cgi-bin/cmd.cgi", data=payload, headers=myHeaders, verify=False)
try:
LOGGER.debug("Result: {0}".format(r.text))
except:
LOGGER.debug("Result: none - check URL/authentification method!")

#check whether request was successful
if r.status_code != 200:
LOGGER.error("Got HTTP status code " + str(r.status_code) + " instead of 200 while scheduling downtime for hostgroup '" + hostgroup + "'. Check URL and logon credentials!")
return False
else:
if "error" in r.text.lower(): LOGGER.error("Unable to schedule downtime for hostgroup '" + hostgroup + "' - please run again with -d / --debug and check HTML output! (does this host exist?!)")
else:
print "Successfully scheduled downtime for hostgroup '" + hostgroup + "'"
return True



def get_libvirt_credentials(credentials, user_data):
#get credentials for libvirt
global LIBVIRT_USERNAME
Expand Down
2 changes: 1 addition & 1 deletion satprep_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def parse_options(args=None):
If you're not defining variables or an authfile you will be prompted to enter your login information.
Checkout the GitHub page for updates: https://github.com/stdevel/satprep'''
parser = OptionParser(description=desc, version="%prog version 0.3")
parser = OptionParser(description=desc, version="%prog version 0.3.3")
#define option groups
genOpts = OptionGroup(parser, "Generic Options")
parser.add_option_group(genOpts)
Expand Down
2 changes: 1 addition & 1 deletion satprep_wa_vcvms.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ def parse_options(args=None):
It is also possible to create an authfile (permissions 0600) for usage with this script (parameters -a/-A). The first line needs to contain the username, the second line should consist of the appropriate password.
If you're not defining variables or an authfile you will be prompted to enter your login information.
Checkout the GitHub wiki for further information: https://github.com/stdevel/satprep/wiki'''
parser = OptionParser(description=desc, version="%prog version 0.3")
parser = OptionParser(description=desc, version="%prog version 0.3.3")

#define option groups
genOpts = OptionGroup(parser, "Generic Options")
Expand Down

0 comments on commit afea9e4

Please sign in to comment.