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

Commit 29dad7d

Browse files
committed
Merge pull request #34 from stdevel/nightly
Release 0.3.2 - minor enhancements and fixes
2 parents 94e006f + 741af07 commit 29dad7d

File tree

2 files changed

+80
-21
lines changed

2 files changed

+80
-21
lines changed

satprep_prepare_maintenance.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from satprep_shared import schedule_downtime, get_credentials, create_snapshot, is_downtime, has_snapshot
1818
import time
1919
import os
20+
from fnmatch import fnmatch
2021

2122
#set logger
2223
LOGGER = logging.getLogger('satprep_prepare_maintenance')
@@ -33,7 +34,17 @@
3334

3435

3536

37+
def is_blacklisted(name, list):
38+
#check whether system is blacklisted
39+
for entry in list:
40+
LOGGER.debug("Checking whether {name} is blacklisted by *{entry}*".format(name=name, entry=entry))
41+
if fnmatch(name.lower(), "*{seek}*".format(seek=entry.lower()) ): return True
42+
return False
43+
44+
45+
3646
def verify():
47+
#verify snapshots and downtimes
3748
global downtimeHosts
3849
global snapshotHosts
3950
global myPrefix
@@ -124,7 +135,7 @@ def verify():
124135

125136

126137
def setDowntimes():
127-
#some globale variables
138+
#set downtimes
128139
global defaultMonUser
129140
global defaultMonPass
130141

@@ -185,7 +196,7 @@ def setDowntimes():
185196

186197

187198
def createSnapshots():
188-
#some globale variables
199+
#create snapshots
189200
global defaultVirtUser
190201
global defaultVirtPass
191202

@@ -281,7 +292,7 @@ def readFile(file):
281292
if (row[repcols["system_prod"]] == "1" and options.nonprodOnly == False) \
282293
or (row[repcols["system_prod"]] != "1" and options.prodOnly == False) \
283294
or (options.prodOnly == False and options.nonprodOnly == False):
284-
if row[repcols["hostname"]].lower() not in options.exclude: downtimeHosts.append(this_name)
295+
if is_blacklisted(row[repcols["hostname"]], options.exclude) == False: downtimeHosts.append(this_name)
285296
LOGGER.debug("Downtime will be scheduled for '" + this_name + "' (P:" + row[repcols["system_prod"]] + ")")
286297

287298
#virtualization, add custom name if defined
@@ -292,7 +303,7 @@ def readFile(file):
292303
if (row[repcols["system_prod"]] == "1" and options.nonprodOnly == False) \
293304
or (row[repcols["system_prod"]] != "1" and options.prodOnly == False) \
294305
or (options.prodOnly == False and options.nonprodOnly == False):
295-
if row[repcols["hostname"]].lower() not in options.exclude: snapshotHosts.append(this_name)
306+
if is_blacklisted(row[repcols["hostname"]], options.exclude) == False: snapshotHosts.append(this_name)
296307
LOGGER.debug("Snapshot will be created for '" + this_name + "' (P:" + row[repcols["system_prod"]] + ")")
297308
else:
298309
LOGGER.debug("Script parameters are avoiding creating snapshot for '" + this_name + "' (P:" + row[repcols["system_prod"]] + ")")
@@ -307,7 +318,7 @@ def readFile(file):
307318
if (row[repcols["system_prod"]] == "1" and options.nonprodOnly == False) \
308319
or (row[repcols["system_prod"]] != "1" and options.prodOnly == False) \
309320
or (options.prodOnly == False and options.nonprodOnly == False):
310-
if row[repcols["hostname"]].lower() not in options.exclude: downtimeHosts.append(this_name)
321+
if is_blacklisted(row[repcols["hostname"]], options.exclude) == False: downtimeHosts.append(this_name)
311322
LOGGER.debug("Downtime will be scheduled for '" + this_name + "' (P:" + row[repcols["system_prod"]] + ")")
312323
else: LOGGER.debug("Script parameters are avoiding scheduling downtime for '" + this_name + "' (P:" + row[repcols["system_prod"]] + ")")
313324

@@ -321,7 +332,7 @@ def readFile(file):
321332
if (row[repcols["system_prod"]] == "1" and options.nonprodOnly == False) \
322333
or (row[repcols["system_prod"]] != "1" and options.prodOnly == False) \
323334
or (options.prodOnly == False and options.nonprodOnly == False):
324-
if row[repcols["hostname"]].lower() not in options.exclude: snapshotHosts.append(this_name)
335+
if is_blacklisted(row[repcols["hostname"]], options.exclude) == False: snapshotHosts.append(this_name)
325336
LOGGER.debug("Snapshot will be created for '" + this_name + "' (P:" + row[repcols["system_prod"]] + ")")
326337
else:
327338
LOGGER.debug("Script parameters are avoiding creating snapshot for '" + this_name + "' (P:" + row[repcols["system_prod"]] + ")")
@@ -353,14 +364,18 @@ def main(options):
353364
#schedule downtimes and create snapshots
354365
if options.skipMonitoring == False: setDowntimes()
355366
if options.skipSnapshot == False: createSnapshots()
367+
#also verify
368+
if options.dryrun == False:
369+
LOGGER.info("Verifying preparation...")
370+
verify()
356371

357372

358373

359374
def parse_options(args=None):
360375
if args is None:
361376
args = sys.argv
362377

363-
# define usage, description, version and load parser
378+
#define usage, description, version and load parser
364379
usage = "usage: %prog [options] snapshot.csv"
365380
desc = '''%prog is used to prepare maintenance for systems managed with Spacewalk, Red Hat Satellite or SUSE Manager. This includes (un)scheduling downtimes in Nagios, Icinga and Shinken and creating/removing snapshots of virtual machines. As this script uses libvirt multiple hypervisors are supported (see GitHub and libvirt documenation). Login credentials are assigned using the following shell variables:
366381
SATELLITE_LOGIN username for Satellite
@@ -436,9 +451,11 @@ def parse_options(args=None):
436451

437452
#tell user that he's a funny guy
438453
if (
439-
(options.skipSnapshot and options.skipMonitoring)
454+
(options.skipSnapshot == True and options.skipMonitoring == True)
440455
or
441456
(options.prodOnly == True and options.nonprodOnly == True)
457+
or
458+
(options.dryrun == True and options.verifyOnly == True)
442459
):
443460
print "Haha, you're funny."
444461
exit(1)

satprep_snapshot.py

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import xmlrpclib
1919
from optparse import OptionParser, OptionGroup
2020
from satprep_shared import check_if_api_is_supported, get_credentials
21+
from unidecode import unidecode
2122

2223

2324

@@ -76,6 +77,8 @@ def parse_options(args=None):
7677
#snapOpts.add_option("-f", "--field", action="append", type="choice", dest="fields", choices=POSSIBLE_FIELDS, metavar="FIELDS", help="defines which fields should be integrated in the report (default: all available)")
7778
#-p / --include-patches
7879
snapOpts.add_option("-p", "--include-patches", action="store_true", default=False, dest="includePatches", help="defines whether package updates that are not part of an erratum shall be included (default: no)")
80+
#-l / --include-locked
81+
snapOpts.add_option("-l", "--include-locked", action="store_true", default=False, dest="includeLocked", help="also includes locked systems (default: no)")
7982

8083
(options, args) = parser.parse_args(args)
8184

@@ -98,8 +101,9 @@ def main(options):
98101
sattelite_url = "http://{0}/rpc/api".format(options.server)
99102
client = xmlrpclib.Server(sattelite_url, verbose=options.debug)
100103
key = client.auth.login(username, password)
101-
102104
check_if_api_is_supported(client)
105+
106+
if options.includeLocked: LOGGER.warning("Snapshot report will also include information about locked systems")
103107

104108
#check whether the output directory/file is writable
105109
if os.access(os.path.dirname(options.output), os.W_OK) or os.access(os.getcwd(), os.W_OK):
@@ -110,7 +114,6 @@ def main(options):
110114
writer = csv.writer(open(options.output, "w"), 'default')
111115

112116
#create header and scan _all_ the systems
113-
#writer.writerow(options.fields)
114117
writer.writerow(DEFAULT_FIELDS)
115118
systems = client.system.listSystems(key)
116119
#counter variable for XMLRPC timeout workaround (https://github.com/stdevel/satprep/issues/5)
@@ -156,29 +159,45 @@ def process_errata(client, key, writer, system):
156159
"errata_date": "update_date"
157160
}
158161

162+
#break if system locked
163+
details = client.system.getDetails(key, system["id"])
164+
if details["lock_status"] != False and options.includeLocked == False:
165+
LOGGER.info("Skipping errata for locked host "
166+
"{system[name]} (SID {system[id]})...".format(
167+
system=system
168+
)
169+
)
170+
return
171+
159172
#TODO: errata_* not working! Implemented a workaround (looking for a "nicer" way to do this)
160173

161174
errata = client.system.getRelevantErrata(key, system["id"])
162175
if not errata:
163-
LOGGER.info("Host {0[name]} (SID {0[id]}) has no relevant errata.".format(system))
176+
LOGGER.debug("Host {0[name]} (SID {0[id]}) has no relevant errata.".format(system))
164177
return
178+
else:
179+
LOGGER.info("Looking at relevant errata for host "
180+
"{system[name]} (SID {system[id]})...".format(
181+
system=system
182+
)
183+
)
165184

166185
for i, erratum in enumerate(errata, start=1):
167-
LOGGER.info("Having a look at relevant errata #{errata} "
186+
LOGGER.debug("Having a look at relevant errata #{errata} "
168187
"for host {system[name]} (SID {system[id]})...".format(
169188
errata=i,
170189
system=system
171190
)
172191
)
173-
192+
174193
valueSet = []
175194
for column in DEFAULT_FIELDS:
176195
try:
177196
valueSet.append(system[columnErrataMapping[column]])
178197
LOGGER.debug("Translated column '" + column + "' in '" + columnErrataMapping[column] + "'")
179198
continue
180199
except KeyError:
181-
# Key not found - probably needs more logic.
200+
#Key not found - probably needs more logic.
182201
LOGGER.debug("Could not find column '" + column + "' in columnErrataMapping")
183202
pass
184203

@@ -286,7 +305,7 @@ def process_errata(client, key, writer, system):
286305
and temp["SYSTEM_MONITORING_HOST"] != "" and
287306
"SYSTEM_MONITORING_HOST_AUTH" in temp and
288307
temp["SYSTEM_MONITORING_HOST_AUTH"] != ""):
289-
temp_vmname = temp_vmname + "@" + temp["SYSTEM_MONITORING_HOST"] + ":" + temp["SYSTEM_MONITORING_HOST_AUTH"]
308+
temp_monname = temp_monname + "@" + temp["SYSTEM_MONITORING_HOST"] + ":" + temp["SYSTEM_MONITORING_HOST_AUTH"]
290309
valueSet.append(temp_monname)
291310
else:
292311
valueSet.append("")
@@ -323,37 +342,60 @@ def process_errata(client, key, writer, system):
323342
else:
324343
valueSet.append("")
325344

345+
#replace unicodes
346+
for i,field in enumerate(valueSet):
347+
if type(field) is unicode:
348+
LOGGER.debug("Converted to ascii: {ascii}".format(
349+
ascii=unidecode(field)
350+
))
351+
valueSet[i] = str(unidecode(field))
352+
326353
writer.writerow(valueSet)
327354

328355

329356

330357
def process_patches(client, key, writer, system):
331358
updates = client.system.listLatestUpgradablePackages(key, system["id"])
332359

360+
#break if system locked
361+
details = client.system.getDetails(key, system["id"])
362+
if details["lock_status"] != False and options.includeLocked == False:
363+
LOGGER.info("Skipping patches for locked host "
364+
"{system[name]} (SID {system[id]})...".format(
365+
system=system
366+
)
367+
)
368+
return
369+
333370
if not updates:
334371
LOGGER.debug("Host {0[name]} (SID {0[id]}) has no relevant updates.".format(system))
335372
return
373+
else:
374+
LOGGER.info("Looking at relevant package updates for host "
375+
"{system[name]} (SID {system[id]})...".format(
376+
system=system
377+
)
378+
)
336379

337380
for i, update in enumerate(updates, start=1):
338-
LOGGER.info("Having a look at relevant package update "
381+
LOGGER.debug("Having a look at relevant package update "
339382
"#{update} for host {system[name]} "
340383
"(SID {system[id]})...".format(
341384
update=i,
342385
system=system
343386
)
344387
)
345-
388+
346389
if client.packages.listProvidingErrata(key, update["to_package_id"]):
347-
# We only add update information if it is not not
348-
# already displayed as part of an erratum
390+
#We only add update information if it is not not
391+
#already displayed as part of an erratum
349392
LOGGER.debug("Dropping update {0[name]} "
350393
"({0[to_package_id]}) as it's already part of "
351394
"an erratum.".format(update)
352395
)
353396
continue
354397

355398
valueSet = []
356-
#for column in options.fields:
357399
for column in DEFAULT_FIELDS:
358400
if column == "hostname":
359401
valueSet.append(system["name"])
@@ -438,7 +480,7 @@ def process_patches(client, key, writer, system):
438480
and temp["SYSTEM_MONITORING_HOST"] != "" and
439481
"SYSTEM_MONITORING_HOST_AUTH" in temp and
440482
temp["SYSTEM_MONITORING_HOST_AUTH"] != ""):
441-
temp_vmname = temp_vmname + "@" + temp["SYSTEM_MONITORING_HOST"] + ":" + temp["SYSTEM_MONITORING_HOST_AUTH"]
483+
temp_monname = temp_monname + "@" + temp["SYSTEM_MONITORING_HOST"] + ":" + temp["SYSTEM_MONITORING_HOST_AUTH"]
442484
valueSet.append(temp_monname)
443485
else:
444486
valueSet.append("")

0 commit comments

Comments
 (0)