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

Commit afea9e4

Browse files
committed
Release 0.3.3
- 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
1 parent d01c6b9 commit afea9e4

File tree

5 files changed

+91
-21
lines changed

5 files changed

+91
-21
lines changed

satprep_install_custominfos.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def parse_options(args=None):
111111
If you're not defining variables or an authfile you will be prompted to enter your login information.
112112
113113
Checkout the GitHub page for updates: https://github.com/stdevel/satprep'''
114-
parser = OptionParser(description=desc, version="%prog version 0.3")
114+
parser = OptionParser(description=desc, version="%prog version 0.3.3")
115115
#define option groups
116116
genOpts = OptionGroup(parser, "Generic Options")
117117
srvOpts = OptionGroup(parser, "Server Options")

satprep_prepare_maintenance.py

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import sys
1515
from optparse import OptionParser, OptionGroup
1616
import csv
17-
from satprep_shared import schedule_downtime, get_credentials, create_snapshot, is_downtime, has_snapshot
17+
from satprep_shared import schedule_downtime, get_credentials, create_snapshot, is_downtime, has_snapshot, schedule_downtime_hostgroup
1818
import time
1919
import os
2020
from fnmatch import fnmatch
@@ -56,14 +56,17 @@ def verify():
5656
#check whether the output directory/file is writable
5757
if os.access(os.getcwd(), os.W_OK):
5858
LOGGER.debug("Output file/directory writable!")
59-
myLog = open(myPrefix+"_satprep.vlog", "w")
59+
myLog = open(myPrefix+"_satprep.vlog", "r+")
60+
#myFile = myLog.readlines()
61+
myFile = myLog.read().splitlines()
62+
LOGGER.debug("vlog before customization: ***\n" + str(myFile))
6063
else:
6164
#directory not writable
6265
LOGGER.error("Output directory NOT writable!")
6366
sys.exit(1)
6467

6568
#check downtimes
66-
if len(downtimeHosts) == 0: LOGGER.info("No downtimes to schedule.")
69+
if len(downtimeHosts) == 0 or options.skipMonitoring: LOGGER.info("No downtimes to verify.")
6770
else:
6871
#check _all_ the downtimes
6972
for host in downtimeHosts:
@@ -90,17 +93,22 @@ def verify():
9093
if result:
9194
#host in downtime
9295
LOGGER.debug("Host '" + thisHost + "' in downtime. :)")
93-
myLog.write("MONOK;" + thisHost + "\n")
96+
#correct or append entry
97+
if "MONCRIT;"+thisHost in myFile and "MONOK;"+thisHost not in myFile: myFile = [h.replace("MONCRIT;"+thisHost, "MONOK;"+thisHost) for h in myFile]
98+
elif "MONOK;"+thisHost not in myFile: myFile.append("MONOK;"+thisHost)
9499
else:
95100
#host NOT in downtime
96101
LOGGER.error("Host '" + thisHost + "' NOT in downtime. :(")
97-
myLog.write("MONCRIT;" + thisHost + "\n")
102+
#correct or append entry
103+
if "MONOK;"+thisHost in myFile and "MONCRIT;"+thisHost not in myFile: myFile = [h.replace("MONOK;"+thisHost, "MONCRIT;"+thisHost) for h in myFile]
104+
elif "MONCRIT;"+thisHost not in myFile: myFile.append("MONCRIT;"+thisHost)
98105

99106
#check snapshots
100-
if len(snapshotHosts) == 0: LOGGER.info("No snapshots to create.")
107+
if len(snapshotHosts) == 0 or options.skipSnapshot: LOGGER.info("No snapshots to verify.")
101108
else:
102109
#check _all_ the snapshots
103110
for host in snapshotHosts:
111+
LOGGER.debug("Checking snapshot for host '" + host + "'...")
104112
#try to get differing host/credentials
105113
if "@" in host and ":" in host:
106114
thisURI = host[host.find("@")+1:host.rfind(":")]
@@ -124,12 +132,20 @@ def verify():
124132
if result:
125133
#snapshot exists
126134
LOGGER.debug("Snapshot for VM '" + thisHost + "' found. :)")
127-
myLog.write("SNAPOK;" + thisHost + "\n")
135+
#correct or append entry
136+
if "SNAPCRIT;"+thisHost in myFile and "SNAPOK;"+thisHost not in myFile: myFile = [h.replace("SNAPCRIT;"+thisHost, "SNAPOK;"+thisHost) for h in myFile]
137+
elif "SNAPOK;"+thisHost not in myFile: myFile.append("SNAPOK;"+thisHost)
128138
else:
129139
#snapshot non-existent
130140
LOGGER.error("No snapshot for VM '" + thisHost + "' found. :(")
131-
myLog.write("SNAPCRIT;" + thisHost + "\n")
132-
#close log file
141+
#correct or append entry
142+
if "SNAPOK;"+thisHost in myFile and "SNAPCRIT;"+thisHost not in myFile: myFile = [h.replace("SNAPOK;"+thisHost, "SNAPCRIT;"+thisHost) for h in myFile]
143+
elif "SNAPCRIT;"+thisHost not in myFile: myFile.append("SNAPCRIT;"+thisHost)
144+
#write vlog file
145+
myLog.seek(0)
146+
LOGGER.debug("File after customization: ***\n" + str(myFile))
147+
for line in myFile:
148+
myLog.write(line + "\n")
133149
myLog.close()
134150

135151

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

163+
#schedule downtimes for hostgroups if given
164+
if len(options.downtimeHostgroups) != 0 and options.tidy == False:
165+
if options.dryrun:
166+
#simulation
167+
for thisHostgroup in options.downtimeHostgroups:
168+
LOGGER.info("I'd like to schedule downtime for hostgroup '" + thisHostgroup + "'...")
169+
else:
170+
#schedule _all_ the downtimes
171+
for thisHostgroup in options.downtimeHostgroups:
172+
LOGGER.info("Scheduling downtime for hostgroup '" + thisHostgroup + "'...")
173+
#get default login if not specified
174+
if defaultMonUser == "": (defaultMonUser, defaultMonPass) = get_credentials("Monitoring", options.monAuthfile)
175+
result = schedule_downtime_hostgroup(options.URL, defaultMonUser, defaultMonPass, thisHostgroup, options.hours, options.comment, options.userAgent, options.noAuth)
176+
return True
177+
147178
#set downtime for affected hosts
148179
for host in downtimeHosts:
149180
#try to get differing host/credentials
@@ -179,10 +210,6 @@ def setDowntimes():
179210
else: output = output + "'..."
180211
LOGGER.info(output)
181212

182-
#setup headers
183-
if len(options.userAgent) > 0: myHeaders = {'User-Agent': options.userAgent}
184-
else: myHeaders = {'User-Agent': 'satprep Toolkit (https://github.com/stdevel/satprep)'}
185-
186213
#(un)schedule downtime
187214
if thisURI != "" and thisCred != "":
188215
#get username and password
@@ -361,9 +388,9 @@ def main(options):
361388
#verify only
362389
verify()
363390
else:
364-
#schedule downtimes and create snapshots
365-
if options.skipMonitoring == False: setDowntimes()
391+
#create snapshots and schedule downtimes
366392
if options.skipSnapshot == False: createSnapshots()
393+
if options.skipMonitoring == False: setDowntimes()
367394
#also verify
368395
if options.dryrun == False:
369396
LOGGER.info("Verifying preparation...")
@@ -387,7 +414,7 @@ def parse_options(args=None):
387414
388415
Check-out the GitHub documentation (https://github.com/stdevel/satprep) for further information.
389416
'''
390-
parser = OptionParser(usage=usage, description=desc, version="%prog version 0.3")
417+
parser = OptionParser(usage=usage, description=desc, version="%prog version 0.3.3")
391418
#define option groups
392419
genOpts = OptionGroup(parser, "Generic Options")
393420
monOpts = OptionGroup(parser, "Monitoring Options")
@@ -428,11 +455,13 @@ def parse_options(args=None):
428455
#-u / --monitoring-url
429456
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)")
430457
#-t / --hours
431-
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)")
458+
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)")
432459
#-x / --no-auth
433460
monOpts.add_option("-x", "--no-auth", action="store_true", default=False, dest="noAuth", help="disables HTTP basic auth (default: no)")
434461
#-A / --user-agent
435462
monOpts.add_option("-A", "--user-agent", action="store", default="", metavar="AGENT", dest="userAgent", help="sets a custom HTTP user agent")
463+
#-g / --downtime-hostgroup
464+
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.")
436465

437466
#VM OPTIONS
438467
#-K / --skip-snapshot

satprep_shared.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def schedule_downtime(url, monUsername, monPassword, host, hours, comment, agent
169169

170170
#check whether request was successful
171171
if r.status_code != 200:
172-
LOGGER.error("Got HTTP status code " + str(r.status_code) + " instead of 200 while scheduling downtime for host '" + host + "'. Check URL and logon credentials!")
172+
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!")
173173
return False
174174
else:
175175
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?!)")
@@ -180,6 +180,47 @@ def schedule_downtime(url, monUsername, monPassword, host, hours, comment, agent
180180

181181

182182

183+
def schedule_downtime_hostgroup(url, monUsername, monPassword, hostgroup, hours, comment, agent="", noAuth=False):
184+
#schedule downtime for hostgroup
185+
#setup headers
186+
if len(agent) > 0: myHeaders = {'User-Agent': agent}
187+
else: myHeaders = {'User-Agent': 'satprep Toolkit (https://github.com/stdevel/satprep)'}
188+
LOGGER.debug("Setting headers: {0}".format(myHeaders))
189+
190+
#setup start and end time for downtime
191+
current_time=time.strftime("%Y-%m-%d %H:%M:%S")
192+
end_time=format(datetime.now() + timedelta(hours=int(hours)), '%Y-%m-%d %H:%M:%S')
193+
LOGGER.debug("current_time: {0}".format(current_time))
194+
LOGGER.debug("end_time: {0}".format(end_time))
195+
196+
#setup payload
197+
#NOTE: there is no way to unschedule downtimes for all hosts/services in a hostgroup
198+
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'}
199+
LOGGER.debug("payload: {0}".format(payload))
200+
201+
#setup HTTP session
202+
s = requests.Session()
203+
if noAuth == False: s.auth = HTTPBasicAuth(monUsername, monPassword)
204+
205+
#send POST request
206+
r = s.post(url+"/cgi-bin/cmd.cgi", data=payload, headers=myHeaders, verify=False)
207+
try:
208+
LOGGER.debug("Result: {0}".format(r.text))
209+
except:
210+
LOGGER.debug("Result: none - check URL/authentification method!")
211+
212+
#check whether request was successful
213+
if r.status_code != 200:
214+
LOGGER.error("Got HTTP status code " + str(r.status_code) + " instead of 200 while scheduling downtime for hostgroup '" + hostgroup + "'. Check URL and logon credentials!")
215+
return False
216+
else:
217+
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?!)")
218+
else:
219+
print "Successfully scheduled downtime for hostgroup '" + hostgroup + "'"
220+
return True
221+
222+
223+
183224
def get_libvirt_credentials(credentials, user_data):
184225
#get credentials for libvirt
185226
global LIBVIRT_USERNAME

satprep_snapshot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def parse_options(args=None):
4747
If you're not defining variables or an authfile you will be prompted to enter your login information.
4848
4949
Checkout the GitHub page for updates: https://github.com/stdevel/satprep'''
50-
parser = OptionParser(description=desc, version="%prog version 0.3")
50+
parser = OptionParser(description=desc, version="%prog version 0.3.3")
5151
#define option groups
5252
genOpts = OptionGroup(parser, "Generic Options")
5353
parser.add_option_group(genOpts)

satprep_wa_vcvms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ def parse_options(args=None):
204204
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.
205205
If you're not defining variables or an authfile you will be prompted to enter your login information.
206206
Checkout the GitHub wiki for further information: https://github.com/stdevel/satprep/wiki'''
207-
parser = OptionParser(description=desc, version="%prog version 0.3")
207+
parser = OptionParser(description=desc, version="%prog version 0.3.3")
208208

209209
#define option groups
210210
genOpts = OptionGroup(parser, "Generic Options")

0 commit comments

Comments
 (0)