#!/usr/bin/python ################################################################################################## # satellite_errata_report (use satellite_errata_report -h or --help for usage # # Please use a read-only account to access the Satellite API. These could be set as the default # # in the below parser arguments for username and password... # # below to these values. Alternatively, username and password can be specifed on the commandline # # # ################################################################################################## import json import sys import argparse try: import requests except ImportError: print "Please install the python-requests module." sys.exit(-1) def get_json(location, username, password): # Performs a GET using the passed URL location location += "?per_page=10000" r = requests.get(location, auth=(username, password),verify=False) return r.json() def main(): parser = argparse.ArgumentParser(description="Satellite Errata Reporter") # Arguments parser.add_argument("-u", "--username", type=str.lower, help="Username to access Satellite", action="store", default='') parser.add_argument("-p", "--password", type=str, help="Password to access Satellite", action="store", default='') parser.add_argument("-n", "--server", type=str.lower, help="Satellite server (default: localhost)", default='localhost') parser.add_argument("-o", "--organization", type=str.lower, nargs="*", help="Filter on this space-delimited list of organization(s)", default='') parser.add_argument("-e", "--environment", type=str.lower, nargs="*", help="Filter on this space-delimited list of lifecycle environments", default='') parser.add_argument("-c", "--collection", type=str.lower, nargs="*", help="Filter on and group by this space-delimited list of host collections", default='') parser.add_argument("-t", "--type", type=str.lower, nargs="*", help="Filter on this space-delimeted list of errata types (bugfix, enhancement, and/or security)", default='') parser.add_argument("-s", "--severity", type=str.lower, nargs="*", help="Filter on this space-delimited list of severities (critical, important, moderate, low)", default='') args = parser.parse_args() # Check username and password if not (args.username and args.password): print "No complete account information provided, exiting" exit (-1) # set up api url sat_api = "http://%s/katello/api/v2/" % args.server katello_api = "http://%s/katello/api/" % args.server # set up initial stuff prefix = "- " systems_fetched = False system_count = 0 system_errata_count = 0 # Loop through organizations and skip the ones we don't want orgs = get_json(sat_api + "organizations/", args.username, args.password) for org in orgs['results']: if args.organization and org['name'].lower not in args.organization: continue print "\nErrata for organization '%s':" % org['name'] if args.collection: # Loop through the host collections, skip the one we don't want collections = get_json(sat_api + "organizations/" + str(org['id']) + "/host_collections/", args.username, args.password) for collection in collections['results']: if collection['name'].lower() not in args.collection: continue print "\n" + prefix + "Errata for Host Collection '%s':" % collection['name'] prefix = " - " # Get the systems in this host collection systems = get_json(sat_api + "host_collections/" + str(collection['id']) + "/systems/", args.username, args.password) systems_fetched = True else: # Get the systems in this Organization systems = get_json(sat_api + "organizations/" + str(org['id']) + "/systems/", args.username, args.password) systems_fetched = True if not systems_fetched: continue # loop through the systems fetched from the collection *or* the organization for system in systems['results']: system_errata = get_json(sat_api + "systems/" + system['uuid'] + "/errata", args.username, args.password) first = True # filter on lifecycle environment(s) (if specified) environment = system['environment']['name'].lower() if args.environment and environment not in args.environment: continue # Get all available Errata for System for system_erratum in system_errata['results']: # filter on type(s) (if specified) type = system_erratum['type'].lower() if args.type and type not in args.type: continue # filter on severity(s) (if specified) if type == "security" and "security" in args.type and args.severity: severity = system_erratum['title'].split(":")[0].encode('ascii','ignore').lower() if severity not in args.severity: continue # We have an erratum, print system if this is the first if first: system_count += 1 first = False print "\n" + prefix + system['name'], "("+system['environment']['name']+")\n" # print the erratum id, type and title (with severity included in the title) print " " + prefix + "%s: %s: %s" % (system_erratum['errata_id'],system_erratum['type'],system_erratum['title']) # Count the errata we find system_errata_count += 1 if not first: print # print statistics if system_errata_count: print "\nNumber of errata to apply: %s" % system_errata_count print "Number of systems affected: %s" % system_count else: print "\nNo errata found for this selection" print if __name__ == "__main__": main()