diff --git a/checks/cisco_api_status b/checks/cisco_api_status index aed0a8e530854e76334cd6e2c4bb85c3f0f6e4b5..a2dc7fe1ac62ae2f9247d3634504d84a40832dc1 100644 --- a/checks/cisco_api_status +++ b/checks/cisco_api_status @@ -13,42 +13,41 @@ def cisco_api_status_arguments(params): # example # {'psirt': {'warn-severity': 3, 'warn-days': 31, 'crit-days': 7, 'crit-severity': 1}} - # print params if params: if params.get('psirt'): - if params.get('psirt').get('crit-days') is not None: + if params.get('psirt').get('crit-days'): args.append('--psirt-crit-days %s' % params.get('psirt').get('crit-days')) - if params.get('psirt').get('warn-days') is not None: + if params.get('psirt').get('warn-days'): args.append('--psirt-warn-days %s' % params.get('psirt').get('warn-days')) - if params.get('psirt').get('warn-severity') is not None: + if params.get('psirt').get('warn-severity'): args.append('--psirt-warn-severity %s' % params.get('psirt').get('warn-severity')) - if params.get('psirt').get('crit-severity') is not None: + if params.get('psirt').get('crit-severity'): args.append('--psirt-crit-severity %s' % params.get('psirt').get('crit-severity')) - if params.get('psirt').get('not-active') is not None: + if params.get('psirt').get('not-active'): args.append('--psirt-not-active %s' % params.get('psirt').get('not-active')) if params.get('eox'): - if params.get('eox').get('crit-new') is not None: + if params.get('eox').get('crit-new'): args.append('--eox-crit-new %s' % params.get('eox').get('crit-new')) - if params.get('eox').get('warn-new') is not None: + if params.get('eox').get('warn-new'): args.append('--eox-warn-new %s' % params.get('eox').get('warn-new')) - if params.get('eox').get('crit-change') is not None: + if params.get('eox').get('crit-change'): args.append('--eox-crit-change %s' % params.get('eox').get('crit-change')) - if params.get('eox').get('warn-change') is not None: + if params.get('eox').get('warn-change'): args.append('--eox-warn-change %s' % params.get('eox').get('warn-change')) - if params.get('eox').get('not-active') is not None: + if params.get('eox').get('not-active'): args.append('--eox-not-active %s' % params.get('eox').get('not-active')) if params.get('sn2info'): - if params.get('sn2info').get('crit-change') is not None: + if params.get('sn2info').get('crit-change'): args.append('--sn2info-crit-change %s' % params.get('sn2info').get('crit-change')) - if params.get('sn2info').get('warn-change') is not None : + if params.get('sn2info').get('warn-change'): args.append('--sn2info-warn-change %s' % params.get('sn2info').get('warn-change')) - if params.get('sn2info').get('not-active') is not None: + if params.get('sn2info').get('not-active'): args.append('--sn2info-not-active %s' % params.get('sn2info').get('not-active')) if params.get('suggestion'): - if params.get('suggestion').get('not-active') is not None: + if params.get('suggestion').get('not-active'): args.append('--suggestion-not-active %s' % params.get('suggestion').get('not-active')) # in CMK v1.5.x global variable g_hostname was replaced by API call host_name() diff --git a/inv_cisco_support.mkp b/inv_cisco_support.mkp index 18b622e7747df2acd05515c0c31216b1ef93c364..e5f4fe72bb72b04ea1a6170be4e9a0d6155b8d33 100644 Binary files a/inv_cisco_support.mkp and b/inv_cisco_support.mkp differ diff --git a/inventory/snmp_cisco_contract b/inventory/snmp_cisco_contract index 6700d37f53ec134a61c53111c8e933da5acca5fe..26ebeab64c62cf22a4e064185d35da1d37e3f772 100644 --- a/inventory/snmp_cisco_contract +++ b/inventory/snmp_cisco_contract @@ -1,14 +1,22 @@ #!/usr/bin/python # -*- encoding: utf-8; py-indent-offset: 4 -*- # -# 20.03.2017 : writen by Th.L. to collect/show Cisco hardware contract status +# License: GNU General Public License v2 # -# 29.05.2017 : fixed empty pid handling -# : added serial number cleanup -# 09-04.2018 : removed import -# 04.09.2018 : changes for CMK 1.5.x (inv_tree --> inv_tree_list) -# 05.09.2018 : changes for CMK 1.5.x (replaced global variable g_hostname with api call host_name()) -# 13.08.2019 : chaged variable host_anme to _hostname for cmk1.5 +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2027-03-20 +# +# collect/show Cisco hardware contract status +# +# 2017-05-29 : fixed empty pid handling +# added serial number cleanup +# 2018-04-09 : removed import +# 2018-09-04 : changes for CMK 1.5.x (inv_tree --> inv_tree_list) +# 2018-09-05 : changes for CMK 1.5.x (replaced global variable g_hostname with api call host_name()) +# 2019-08-13 : chaged variable host_anme to _hostname for cmk1.5 +# 2020-08-04 : moved node tree from hardware.system.support to hardware.system +# cleanup create_sn2info_record # # import is done by Check_MK # import logging @@ -17,7 +25,7 @@ import json import ConfigParser -def create_sn2info_record(sn2infofile): +def create_sn2info_record(sn2infofile, optional_columns): sn2info = {} if os.path.isfile(sn2infofile): with open(sn2infofile) as f: @@ -27,52 +35,26 @@ def create_sn2info_record(sn2infofile): sn2info.update({'Last_checked': time.strftime('%Y-%m-%d', time.localtime(modifytime)) }) - # get info's from sn2info File - serial_number = sn2inforecord.get('sr_no') - is_covered = sn2inforecord.get('is_covered') - contract_site_customer_name = sn2inforecord.get('contract_site_customer_name') - contract_site_address1 = sn2inforecord.get('contract_site_address1') - contract_site_city = sn2inforecord.get('contract_site_city') - contract_site_state_province = sn2inforecord.get('contract_site_state_province') - contract_site_country = sn2inforecord.get('contract_site_country') - service_line_descr = sn2inforecord.get('service_line_descr') - service_contract_number = sn2inforecord.get('service_contract_number') - covered_product_line_end_date = sn2inforecord.get('covered_product_line_end_date') - parent_sr_no = sn2inforecord.get('parent_sr_no') - warranty_type = sn2inforecord.get('warranty_type') - warranty_type_description = sn2inforecord.get('warranty_type_description') - warranty_end_date = sn2inforecord.get('warranty_end_date') - - # add nonempty info's to sn2inforecord - - if (serial_number is not None) and (serial_number != ''): - sn2info.update({'serial_number': serial_number}) - if (is_covered is not None) and (is_covered != ''): - sn2info.update({'is_covered': is_covered}) - if (contract_site_customer_name is not None) and (contract_site_customer_name != ''): - sn2info.update({'contract_site_customer_name': contract_site_customer_name}) - if (contract_site_address1 is not None) and (contract_site_address1 != ''): - sn2info.update({'contract_site_address1': contract_site_address1}) - if (contract_site_city is not None) and (contract_site_city != ''): - sn2info.update({'contract_site_city': contract_site_city}) - if (contract_site_state_province is not None) and (contract_site_state_province != ''): - sn2info.update({'contract_site_state_province': contract_site_state_province}) - if (contract_site_country is not None) and (contract_site_country != ''): - sn2info.update({'contract_site_country': contract_site_country}) - if (service_line_descr is not None) and (service_line_descr != ''): - sn2info.update({'service_line_descr': service_line_descr}) - if (service_contract_number is not None) and (service_contract_number != ''): - sn2info.update({'service_contract_number': service_contract_number}) - if (covered_product_line_end_date is not None) and (covered_product_line_end_date != ''): - sn2info.update({'covered_product_line_end_date': covered_product_line_end_date}) - if (parent_sr_no is not None) and (parent_sr_no != ''): - sn2info.update({'parent_sr_no': parent_sr_no}) - if (warranty_type is not None) and (warranty_type != ''): - sn2info.update({'warranty_type': warranty_type}) - if (warranty_type_description is not None) and (warranty_type_description != ''): - sn2info.update({'warranty_type_description': warranty_type_description}) - if (warranty_end_date is not None) and (warranty_end_date != ''): - sn2info.update({'warranty_end_date': warranty_end_date}) + # add nonempty values to sn2inforecord + for key, value in [ + ('serial_number', sn2inforecord.get('sr_no')), + ('is_covered', sn2inforecord.get('is_covered')), + ('contract_site_customer_name', sn2inforecord.get('contract_site_customer_name')), + ('contract_site_address1', sn2inforecord.get('contract_site_address1')), + ('contract_site_city', sn2inforecord.get('contract_site_city')), + ('contract_site_state_province', sn2inforecord.get('contract_site_state_province')), + ('contract_site_country', sn2inforecord.get('contract_site_country')), + ('service_line_descr', sn2inforecord.get('service_line_descr')), + ('service_contract_number', sn2inforecord.get('service_contract_number')), + ('covered_product_line_end_date', sn2inforecord.get('covered_product_line_end_date')), + ('parent_sr_no', sn2inforecord.get('parent_sr_no')), + ('warranty_type', sn2inforecord.get('warranty_type')), + ('warranty_type_description', sn2inforecord.get('warranty_type_description')), + ('warranty_end_date', sn2inforecord.get('warranty_end_date')), + ]: + value = value.strip() + if value != '' and key not in optional_columns: + sn2info[key] = value logging.info('create_sn2info_record sn2info: %s' % sn2info) return sn2info @@ -119,7 +101,7 @@ def inv_cisco_contract(info, params): path_request = expand_path(sn2info_dir + '/request/') status_path = expand_path(base_path + '/status') - node = inv_tree_list('hardware.system.support.cisco_contract:') + node = inv_tree_list('hardware.support.cisco_contract:') serials = [] serialscontract = [] @@ -142,15 +124,17 @@ def inv_cisco_contract(info, params): logging.info('raw sn : %s' % physerialnum) logging.info('raw desc : %s' % phydescr) - pid = phymodelname.split()[0].upper() # cut PID at first space sign, change to all Uppercase + # cut PID/SN at first space sign, change to all Uppercase + pid = phymodelname.split()[0].upper() + physerialnum = physerialnum.split()[0].upper() - # drop all PIDs on Black List + # drop all PIDs on Black List, create default node entry for SN if not pid_on_black_list(pid): logging.info('PID not on blacklist: %s' % pid) if phydescr == "": phydescr = 'requested' - physerialnum = physerialnum.split()[0].upper() + # create list of serial numbers to request contract info for serials.append(physerialnum) @@ -167,7 +151,7 @@ def inv_cisco_contract(info, params): # find serial in SER-sn2info-covered if os.path.isfile(path_found + serial): logging.info("Serial number covered: %s" % serial) - serialscontract.append(create_sn2info_record(path_found + serial)) + serialscontract.append(create_sn2info_record(path_found + serial, optionalcolumns)) logging.info("Serial number Record: %s" % serialscontract) # find serial in SER-sn2info-notcovered elif os.path.isfile(path_not_found + serial): @@ -191,17 +175,12 @@ def inv_cisco_contract(info, params): logging.info("Serials contract : %s" % serialscontract) + # update default entrys with data for i in node: # add contract data by serial number for serial in serialscontract: if i.get('serial_number') == serial.get('serial_number'): i.update(serial) - # remove optional columns - logging.info('remove columns: %s' % optionalcolumns) - if optionalcolumns is not None: - for column in optionalcolumns: - logging.info('remove column: %s' % column) - i.pop(column, None) # create and write back api status, will be used for active check cisco_api_status apistatus = {} diff --git a/inventory/snmp_cisco_eox b/inventory/snmp_cisco_eox index d9bf001938e39eb9d845cf7926b89d4ba41d1826..ab1312fbf65e748044914fe4e8be15a6cf836dbf 100644 --- a/inventory/snmp_cisco_eox +++ b/inventory/snmp_cisco_eox @@ -1,14 +1,22 @@ #!/usr/bin/python # -*- encoding: utf-8; py-indent-offset: 4 -*- # -# 20.03.2017 : writen by Th.L. to collect/show Cisco hardware EoX status +# License: GNU General Public License v2 # -# 29.05.2017 : fixed empty pid handling -# : added serial number cleanup -# 09-04.2018 : removed import -# 04.09.2018 : changes for CMK 1.5.x (inv_tree --> inv_tree_list) -# 05.09.2018 : changes for CMK 1.5.x (replaced global variable g_hostname with api call host_name()) -# 13.08.2018 : changed variable host_name to _hostname for cmk 1.5 +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2017-03-20 +# +# collect/show Cisco hardware EoX status +# +# 2017-05-29 : fixed empty pid handling +# added serial number cleanup +# 2018-04-09 : removed import +# 2018-09-04 : changes for CMK 1.5.x (inv_tree --> inv_tree_list) +# 2018-09-05 : changes for CMK 1.5.x (replaced global variable g_hostname with api call host_name()) +# 2018-08-13 : changed variable host_name to _hostname for cmk 1.5 +# 2020-08-04 : code cleanup (create_eox_record function) +# moved node tree from hardware.system.support to hardware.system # # import is done by Check_MK @@ -18,79 +26,52 @@ import json import ConfigParser -def create_eox_record(eoxfile): +def create_eox_record(eoxfile, optional_columns): eox = {} if os.path.isfile(eoxfile): with open(eoxfile) as f: eoxrecord = json.load(f) + modifytime = os.path.getmtime(eoxfile) - eox.update({'Last_checked': time.strftime('%Y-%m-%d', time.localtime(modifytime))}) - eox.update({'pid': eoxrecord.get('EOLProductID')}) - - # get infos from EOX File - ProductIDDescription = eoxrecord.get('ProductIDDescription') - EOXExternalAnnouncementDate = eoxrecord.get('EOXExternalAnnouncementDate').get('value') - EndOfSaleDate = eoxrecord.get('EndOfSaleDate').get('value') - EndOfSvcAttachDate = eoxrecord.get('EndOfSvcAttachDate').get('value') - LastDateOfSupport = eoxrecord.get('LastDateOfSupport').get('value') - ProductBulletinNumber = eoxrecord.get('ProductBulletinNumber') - LinkToProductBulletinURL = eoxrecord.get('LinkToProductBulletinURL') - UpdatedTimeStamp = eoxrecord.get('UpdatedTimeStamp').get('value') - EndOfSecurityVulSupportDate = eoxrecord.get('EndOfSecurityVulSupportDate').get('value') - EndOfSWMaintenanceReleases = eoxrecord.get('EndOfSWMaintenanceReleases').get('value') - EndOfRoutineFailureAnalysisDate = eoxrecord.get('EndOfRoutineFailureAnalysisDate').get('value') - EOXInputType = eoxrecord.get('EOXInputType') + + eox['Last_checked'] = time.strftime('%Y-%m-%d', time.localtime(modifytime)) + eox['pid'] = eoxrecord.get('EOLProductID') # Migration Info EOXMigrationDetails = eoxrecord.get('EOXMigrationDetails') - MigrationProductId = EOXMigrationDetails.get('MigrationProductId') - MigrationInformation = EOXMigrationDetails.get('MigrationInformation') - MigrationProductInfoURL = EOXMigrationDetails.get('MigrationProductInfoURL') - MigrationProductName = EOXMigrationDetails.get('MigrationProductName') - - # add nonempty infos to eoxrecord - if (ProductIDDescription is not None) and (ProductIDDescription != ' '): - eox.update({'ProductIDDescription': ProductIDDescription}) - if (EOXExternalAnnouncementDate is not None) and (EOXExternalAnnouncementDate != ' '): - eox.update({'EOXExternalAnnouncementDate': EOXExternalAnnouncementDate}) - if (EndOfSaleDate is not None) and (EndOfSaleDate != ' '): - eox.update({'EndOfSaleDate': EndOfSaleDate}) - if (EndOfSvcAttachDate is not None) and (EndOfSvcAttachDate != ' '): - eox.update({'EndOfSvcAttachDate': EndOfSvcAttachDate}) - if (LastDateOfSupport is not None) and (LastDateOfSupport != ' '): - eox.update({'LastDateOfSupport': LastDateOfSupport}) - if (ProductBulletinNumber is not None) and (ProductBulletinNumber != ' '): - eox.update({'ProductBulletinNumber': ProductBulletinNumber}) - if (LinkToProductBulletinURL is not None) and (LinkToProductBulletinURL != ' '): - eox.update({'LinkToProductBulletinURL': LinkToProductBulletinURL}) - if (UpdatedTimeStamp is not None) and (UpdatedTimeStamp != ' '): - eox.update({'UpdatedTimeStamp': UpdatedTimeStamp}) - if (EndOfSecurityVulSupportDate is not None) and (EndOfSecurityVulSupportDate != ' '): - eox.update({'EndOfSecurityVulSupportDate': EndOfSecurityVulSupportDate}) - if (EndOfSWMaintenanceReleases is not None) and (EndOfSWMaintenanceReleases != ' '): - eox.update({'EndOfSWMaintenanceReleases': EndOfSWMaintenanceReleases}) - if (EndOfRoutineFailureAnalysisDate is not None) and (EndOfRoutineFailureAnalysisDate != ' '): - eox.update({'EndOfRoutineFailureAnalysisDate' : EndOfRoutineFailureAnalysisDate}) - # Migration Info - if (MigrationProductId is not None) and (MigrationProductId != ' '): - eox.update({'MigrationProductId': MigrationProductId}) - if (MigrationInformation is not None) and (MigrationInformation != ' '): - eox.update({'MigrationInformation': MigrationInformation}) - if (MigrationProductInfoURL is not None) and (MigrationProductInfoURL != ' '): - eox.update({'MigrationProductInfoURL': MigrationProductInfoURL}) - if (MigrationProductName is not None) and (MigrationProductName != ' '): - eox.update({'MigrationProductName': MigrationProductName}) + for key, value in [ + ('ProductIDDescription', eoxrecord.get('ProductIDDescription', '')), + ('EOXExternalAnnouncementDate', eoxrecord.get('EOXExternalAnnouncementDate').get('value', '')), + ('EndOfSaleDate', eoxrecord.get('EndOfSaleDate').get('value', '')), + ('EndOfSvcAttachDate', eoxrecord.get('EndOfSvcAttachDate').get('value', '')), + ('LastDateOfSupport', eoxrecord.get('LastDateOfSupport').get('value', '')), + ('ProductBulletinNumber', eoxrecord.get('ProductBulletinNumber', '')), + ('LinkToProductBulletinURL', eoxrecord.get('LinkToProductBulletinURL', '')), + ('UpdatedTimeStamp', eoxrecord.get('UpdatedTimeStamp').get('value', '')), + ('EndOfSecurityVulSupportDate', eoxrecord.get('EndOfSecurityVulSupportDate').get('value', '')), + ('EndOfSWMaintenanceReleases', eoxrecord.get('EndOfSWMaintenanceReleases').get('value', '')), + ('EndOfRoutineFailureAnalysisDate', eoxrecord.get('EndOfRoutineFailureAnalysisDate').get('value', '')), + + # Migration Info + ('MigrationProductId', EOXMigrationDetails.get('MigrationProductId', '')), + ('MigrationInformation', EOXMigrationDetails.get('MigrationInformation', '')), + ('MigrationProductInfoURL', EOXMigrationDetails.get('MigrationProductInfoURL', '')), + ('MigrationProductName', EOXMigrationDetails.get('MigrationProductName', '')), + ]: + value = value.strip() + if value != '' and key not in optional_columns: + eox[key] = value # add serial if EoX from get_eox_by_serial + EOXInputType = eoxrecord.get('EOXInputType') if EOXInputType == 'ShowEOXBySerialNumber': - eox.update({'serial_number': eoxrecord.get('EOXInputValue')}) + eox['serial_number'] = eoxrecord.get('EOXInputValue') return eox def inv_cisco_eox(info, params): - set_loglevel() # list of PIDs to drop @@ -109,6 +90,7 @@ def inv_cisco_eox(info, params): 'MigrationProductInfoURL', 'MigrationProductName', ] + base_path = '~/var/ciscoapi' conf_file = '~/etc/ciscoapi/ciscoapi.conf' conf_file = os.path.expanduser(conf_file) @@ -151,7 +133,7 @@ def inv_cisco_eox(info, params): status_path = expand_path(base_path + '/status') - node = inv_tree_list('hardware.system.support.cisco_eox:') + node = inv_tree_list('hardware.support.cisco_eox:') pids = [] pidseox = [] @@ -177,18 +159,17 @@ def inv_cisco_eox(info, params): logging.info('raw sn : %s' % physerialnum) logging.info('raw desc : %s' % phydescr) - # cut PID at first space sign, change to all Uppercase + # cut PID/SN at first space sign, change to all Uppercase pid = phymodelname.split()[0].upper() + physerialnum = physerialnum.split()[0].upper() - # drop all PIDs on Black List + # drop all PIDs/SNs on Black List if not pid_on_black_list(pid) and not sn_on_black_list(physerialnum): logging.info('PID not on blacklist: %s' % pid) if phydescr == "": phydescr = 'requested' - physerialnum = physerialnum.split()[0].upper() - # check if PID on bad list, if so try serial number if pid_on_bad_list(pid) or always_use_serial: logging.info('PID on bad list: %s' % pid) @@ -198,6 +179,7 @@ def inv_cisco_eox(info, params): pids.append(pid) logging.info('PID not on bad list: %s' % pid) + # create default node entry for PID/SN node.append({ "serial_number" : physerialnum, "pid" : pid, @@ -216,7 +198,7 @@ def inv_cisco_eox(info, params): # find pid in PID-EOX-known if os.path.isfile(path_found_pid + pidfile): logging.info("PID known: %s" % pid) - pidseox.append(create_eox_record(path_found_pid + pidfile)) + pidseox.append(create_eox_record(path_found_pid + pidfile, optionalcolumns)) logging.info("EOX Record: %s" % pidseox) # find pid in PID-EOX-unknown elif os.path.isfile(path_not_found_pid + pidfile): @@ -244,7 +226,7 @@ def inv_cisco_eox(info, params): # find serial in SER-EOX-known if os.path.isfile(path_found_ser + serial): logging.info("Serialnumber known: %s" % serial) - serialseox.append(create_eox_record(path_found_ser + serial)) + serialseox.append(create_eox_record(path_found_ser + serial, optionalcolumns)) logging.info("Serialnumber Record: %s" % serialseox) # find serial in SER-EOX-unknown elif os.path.isfile(path_not_found_ser + serial): @@ -269,6 +251,7 @@ def inv_cisco_eox(info, params): logging.info("PID EoX : %s" % pidseox) logging.info("Serials EoX : %s" % serialseox) + # update default entrys with data for i in node: # add EoX data by pid for pid in pidseox: @@ -278,12 +261,6 @@ def inv_cisco_eox(info, params): for serial in serialseox: if i.get('serial_number') == serial.get('serial_number'): i.update(serial) - # remove optional columns - logging.info('remove columns: %s' % optionalcolumns) - if optionalcolumns is not None: - for column in optionalcolumns: - logging.info('remove column: %s' % column) - i.pop(column, None) # create and write back api status, will be used for active check cisco_api_status apistatus = {} diff --git a/inventory/snmp_cisco_suggestion b/inventory/snmp_cisco_suggestion index 88bcfba8648848ddacbae9a1ac0301054b7061e7..45fd11b1346a93da3801f0d53f913c8120bd80b5 100644 --- a/inventory/snmp_cisco_suggestion +++ b/inventory/snmp_cisco_suggestion @@ -69,8 +69,8 @@ def create_suggested_record(pidfile, optionalcolumns): for product in cleanrecord: for suggestion in product.get('suggestion'): for key in suggestion.keys(): - temp_value = suggestion.get(key) - if (temp_value is None) or (temp_value == '') or (key in optionalcolumns): + temp_value = suggestion.get(key, '') + if temp_value == '' or key in optionalcolumns: suggestion.pop(key) # move content from 'suggestion'.'product'.'suggestion' one stage up into 'suggestion'.'product' @@ -257,12 +257,12 @@ def inv_cisco_suggestion(info, params): for product in suggestions: if i.get('pid') == product.get('pid'): i.update(product) - # remove optional columns - logging.debug('remove columns: %s' % optionalcolumns) - if optionalcolumns is not None: - for column in optionalcolumns: - logging.debug('remove column: %s' % column) - i.pop(column, None) + # remove optional columns (already done by create_suggested_record) + #logging.debug('remove columns: %s' % optionalcolumns) + #if optionalcolumns is not None: + # for column in optionalcolumns: + # logging.debug('remove column: %s' % column) + # i.pop(column, None) # create and write back api status, will be used for active checks apistatus = {} diff --git a/lib/nagios/plugins/cisco_api_status b/lib/nagios/plugins/cisco_api_status index b5323bbac4001f87ef9865cc4439ad9d6a4425c2..a95e1d6e7b2e748e576798489551a8d2b802bbf8 100755 --- a/lib/nagios/plugins/cisco_api_status +++ b/lib/nagios/plugins/cisco_api_status @@ -1,14 +1,12 @@ #!/usr/bin/python # encoding: utf-8 -# Monitor Cisco API plugins for CheckMK -# Author: thl-cmk[al]outlook[dot]com -# -# -# 15.03.2020: changed getopt to argparse + + import os -import argparse +import sys +import getopt import ConfigParser import json from datetime import datetime @@ -16,6 +14,61 @@ import logging import sys +def bail_out(reason): + # set logg modul name <file>:<module>.<function> + logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) + + sys.stderr.write("FATAL ERROR: %s\n" % reason) + sys.exit(3) + + +def usage(): + # set logg modul name <file>:<module>.<function> + logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) + + print """cisco_api_atatus [options] TARGET + +Check status of Cisco APIs for TARGET. TARGET is the hostname used by Check_MK. + +Other options: + + PSIRT options + --psirt-crit-severity <severity> if new/updated advisory equal or above severity set outcome to critical + --psirt-crit-days <days> set outcome to critical is new/updated advisory not older then days + --psirt-warn-severity <severity> if new/updated advisory equal or above severity set outcome to warning + --psirt-warn-days <days> set outcome to warning is new/updated advisory not older then days + --psirt-not-active <status> set outcome to status if PSIRT API is not active + + --psirt-crit-days should be less then --psirt-warn-days + --psirt-warn-severity should be less then --psirt-crit-severity + + EoX options + --eox-crit-new <days> set outcome to critical if new announcement not older then days + --eox-warn-new <days> set outcome to warning if new announcement not older then days + --eox-crit-change <days> set outcome to critical if announcement is about to change in lees then days + --eox-warn-change <days> set outcome to warning if announcement is about to change in lees then days + --eox-not-active <status> set outcome to status if EoX API is not active + + sn2info (contract) options + --sn2info-crit-change <days> set outcome to critical if contract is about to change in lees then days + --sn2info-warn-change <days> set outcome to warning if contract is about to change in lees then days + --sn2info-not-active <status> set outcome to status if sn2info API is not active + + suggestion options + --suggestion-not-active <status> set outcome to status if suggestion API is not active + + + <severity> is one of : 1 (Critical), 2 (High), 3 (Medium), 4 (Low), 0 (All) + <days> : >= 1 + <status> is one of : 0 (Ok), 1 (Warning), 2 (Critical) + + + -h, --help show this help and exit + --debug show Python exceptions verbosely + +""" + + # check if dir exists, if not try to create it. # return True if dir exists or creation was ok. # return False if dir not exists and creation was not ok @@ -47,7 +100,7 @@ def expand_path(path): return path -def check_eox_status(apistatus, options, cmd_args): +def check_eox_status(apistatus, options): # set logg modul name <file>:<module>.<function> logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) @@ -59,10 +112,10 @@ def check_eox_status(apistatus, options, cmd_args): lastrun = apistatus.get('lastrun') refresh_known = options.get('refresh_known', 31) refresh_unknown = options.get('refresh_unknown', 7) - crit_new = cmd_args.eox_crit_new - warn_new = cmd_args.eox_warn_new - crit_change = cmd_args.eox_crit_change - warn_change = cmd_args.eox_warn_change + crit_new = options.get('crit-new', 0) + warn_new = options.get('warn-new', 0) + crit_change = options.get('crit-change', 0) + warn_change = options.get('warn-change', 0) for entry in lastrun: last_checked = entry.get('Last_checked') @@ -89,7 +142,7 @@ def check_eox_status(apistatus, options, cmd_args): # check if date is about to change for key in entry.keys(): - if key in EoL_dates and entry.get(key) != '': + if key in EoL_dates: change_days = (datetime.strptime(entry.get(key), '%Y-%m-%d').date() - datetime.now().date()).days change_text = EoL_dates_desc.get(key, 'key not found') if ((change_days < crit_change) or (change_days < warn_change)) and (change_days >= 0): @@ -136,7 +189,7 @@ def check_eox_status(apistatus, options, cmd_args): return output, long_output, status -def check_psirt_status(apistatus, options, cmd_args): +def check_psirt_status(apistatus, options): # set logg modul name <file>:<module>.<function> logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) @@ -159,10 +212,10 @@ def check_psirt_status(apistatus, options, cmd_args): refresh_found = options.get('refresh_found', 1) refresh_notfound = options.get('refresh_notfound', 1) - warn_days = cmd_args.psirt_warn_days - crit_days = cmd_args.psirt_crit_days - warn_severity = cmd_args.psirt_warn_severity - crit_severity = cmd_args.psirt_crit_severity + warn_days = options.get('warn-days') + crit_days = options.get('crit-days') + warn_severity = options.get('warn-severity', 0) + crit_severity = options.get('crit-severity', 0) if (psirt_status == 'found') and (last_refresh > refresh_found): max_refresh_known = last_refresh @@ -201,7 +254,7 @@ def check_psirt_status(apistatus, options, cmd_args): return output, long_output, status -def check_sn2info_status(apistatus, options, cmd_args): +def check_sn2info_status(apistatus, options): # set logg modul name <file>:<module>.<function> logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) @@ -214,8 +267,8 @@ def check_sn2info_status(apistatus, options, cmd_args): refresh_covered = options.get('refresh_covered', 31) refresh_notcovered = options.get('refresh_notcovered', 7) - crit_change = cmd_args.sn2info_crit_change - warn_change = cmd_args.sn2info_warn_change + crit_change = options.get('crit-change', 0) + warn_change = options.get('warn-change', 0) for entry in lastrun: last_checked = entry.get('Last_checked') @@ -269,7 +322,7 @@ def check_sn2info_status(apistatus, options, cmd_args): return output, long_output, status -def check_suggestion_status(apistatus, options, cmd_args): +def check_suggestion_status(apistatus, options): # set logg modul name <file>:<module>.<function> logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) @@ -324,6 +377,7 @@ def main(): output = '' long_output = '' apistatus = {} + target = '' loglevel = 'warning' @@ -367,29 +421,79 @@ def main(): os.unsetenv("LANG") - parser = argparse.ArgumentParser() - parser.add_argument('TARGET', type=str, help='Host to check (exact name form CheckMK)') - parser.add_argument('--psirt-crit-days', type=int, default=0, help='set check status to critical if new/updated advisory not older then days, should be less then --psirt-warn-days') - parser.add_argument('--psirt-warn-days', type=int, default=0, help='set check status to warning if new/updated advisory not older then days') - parser.add_argument('--psirt-crit-severity', type=int, default=0, choices=[0, 1, 2, 3, 4], help='if new/updated advisory equal or above severity {All, Critical, High, Medium, Low} set check status to critical') - parser.add_argument('--psirt-warn-severity', type=int, default=0, choices=[0, 1, 2, 3, 4], help='if new/updated advisory equal or above severity {All, Critical, High, Medium, Low} set check status to warning, should be less then --psirt-crit-severity') - parser.add_argument('--psirt-not-active', type=int, choices=[0, 1, 2], help='set check status to {Ok, Warn, Crit} if PSIRT API is not active') - parser.add_argument('--eox-crit-new', type=int, default=0, help='set check status to critical if new announcement not older then days') - parser.add_argument('--eox-warn-new', type=int, default=0, help='set check status to warning if new announcement not older then days') - parser.add_argument('--eox-crit-change', type=int, default=0, help='set check status to critical if announcement is about to change in lees then days') - parser.add_argument('--eox-warn-change', type=int, default=0, help='set check status to warning if announcement is about to change in lees then days') - parser.add_argument('--eox-not-active', type=int, choices=[0, 1, 2], help='set check status to {Ok, Warn, Crit} if EoX API is not active') - parser.add_argument('--sn2info-crit-change', type=int, default=0, help='set check status to critical if contract is about to change in lees then days') - parser.add_argument('--sn2info-warn-change', type=int, default=0, help='set check status to warning if contract is about to change in lees then days') - parser.add_argument('--sn2info-not-active', type=int, choices=[0, 1, 2], help='set check status to {Ok, Warn, Crit} if sn2info API is not active') - parser.add_argument('--suggestion-not-active', type=int, choices=[0, 1, 2], help='set check status to {Ok, Warn, Crit} if suggestion API is not active') - - parser.parse_args() - cmd_args = parser.parse_args() - # print 'cmd_args: {}'.format(cmd_args) - - target = cmd_args.TARGET - not_active = [] + # short_options = "hw:W:c:C:nTI" + short_options = 'h' + long_options = ['help', 'debug', + 'psirt-crit-severity=', 'psirt-crit-days=', 'psirt-warn-severity=', 'psirt-warn-days=', 'psirt-not-active=', + 'eox-not-active=', 'eox-crit-new=', 'eox-warn-new=', 'eox-crit-change=', 'eox-warn-change=', + 'sn2info-not-active=', 'sn2info-crit-change=', 'sn2info-warn-change=', + 'suggestion-not-active=', + ] + + try: + opts, args = getopt.getopt(sys.argv[1:], short_options, long_options) + + # first parse modifers + # for o, a in opts: + # if o in [ '-v', '--verbose' ]: + # opt_verbose += 1 + # elif o in [ '-d', '--debug' ]: + # opt_debug = True + # elif o in [ '-w', '-W', '-c', '-C' ]: + # routes.append((o[1], a)) + # elif o == '-n': + # opt_nodns = True + # elif o in [ '-T', '-I' ]: + # opt_method = o + + # now handle action options + for o, a in opts: + if o in ['--psirt-crit-severity']: + opt_psirt.update({'crit-severity': int(a)}) + if o in ['--psirt-warn-severity']: + opt_psirt.update({'warn-severity': int(a)}) + if o in ['--psirt-crit-days']: + if int(a) > 0: + opt_psirt.update({'crit-days': int(a)}) + if o in ['--psirt-warn-days']: + if int(a) > 0: + opt_psirt.update({'warn-days': int(a)}) + if o in ['--psirt-not-active']: + opt_psirt.update({'not-active': int(a)}) + + if o in ['--eox-not-active']: + opt_eox.update({'not-active': int(a)}) + if o in ['--eox-crit-new']: + opt_eox.update({'crit-new': int(a)}) + if o in ['--eox-warn-new']: + opt_eox.update({'warn-new': int(a)}) + if o in ['--eox-crit-change']: + opt_eox.update({'crit-change': int(a)}) + if o in ['--eox-warn-change']: + opt_eox.update({'warn-change': int(a)}) + + if o in ['--sn2info-not-active']: + opt_sn2info.update({'not-active': int(a)}) + if o in ['--sn2info-crit-change']: + opt_sn2info.update({'crit-change': int(a)}) + if o in ['--sn2info-warn-change']: + opt_sn2info.update({'warn-change': int(a)}) + + if o in ['--suggestion-not-active']: + opt_suggestion.update({'not-active': int(a)}) + + if o in ['-h', '--help']: + usage() + sys.exit(0) + + if len(args) < 1: + bail_out("Please specify the target.") + + target = args[0] + + + except Exception, e: + bail_out(e) eox_output = '' eox_long_output = '' @@ -411,16 +515,16 @@ def main(): output = 'Cisco API active.' with open(ciscoapistatus + target) as f: apistatus = json.load(f) - long_output = 'active API(s) found: ' + ', '.join(apistatus.keys()) + long_output = 'active APIs found: ' + ', '.join(apistatus.keys()) for key in apistatus.keys(): if key == 'eox': - eox_output, eox_long_output, eox_status = check_eox_status(apistatus.get(key), opt_eox, cmd_args) + eox_output, eox_long_output, eox_status = check_eox_status(apistatus.get(key), opt_eox) if key == 'psirt': - psirt_output, psirt_long_output, psirt_status = check_psirt_status(apistatus.get(key), opt_psirt, cmd_args) + psirt_output, psirt_long_output, psirt_status = check_psirt_status(apistatus.get(key), opt_psirt) if key == 'sn2info': - sn2info_output, sn2info_long_output, sn2info_status = check_sn2info_status(apistatus.get(key), opt_sn2info, cmd_args) + sn2info_output, sn2info_long_output, sn2info_status = check_sn2info_status(apistatus.get(key), opt_sn2info) if key == 'suggestion': - suggestion_output, suggestion_long_output, suggestion_status = check_suggestion_status(apistatus.get(key), opt_suggestion, cmd_args) + suggestion_output, suggestion_long_output, suggestion_status = check_suggestion_status(apistatus.get(key), opt_suggestion) long_output += eox_long_output + sn2info_long_output + psirt_long_output + suggestion_long_output + '\n' @@ -434,24 +538,26 @@ def main(): if status > 0: output += ' (see long output for details)' - if cmd_args.psirt_not_active is not None and ('psirt' not in apistatus.keys()): - status = max(status, cmd_args.psirt_not_active) - not_active.append('PSIRT') - - if cmd_args.eox_not_active is not None and ('eox' not in apistatus.keys()): - status = max(status, cmd_args.eox_not_active) - not_active.append('EoX') - - if cmd_args.sn2info_not_active is not None and ('sn2info' not in apistatus.keys()): - status = max(status, cmd_args.sn2info_not_active) - not_active.append('SN2INFO') - - if cmd_args.suggestion_not_active is not None and ('suggestion' not in apistatus.keys()): - status = max(status, cmd_args.suggestion_not_active) - not_active.append('SUGGESTION') - - if len(not_active) > 0: - output += ' Not active API(s): {}'.format(', '.join(not_active)) + if opt_psirt.get('not-active') and ('psirt' not in apistatus.keys()): + if status <= opt_psirt.get('not-active'): + status = opt_psirt.get('not-active') + output += ' PSIRT API not active.' + + if opt_eox.get('not-active') and ('eox' not in apistatus.keys()): + if status <= opt_eox.get('not-active'): + status = opt_eox.get('not-active') + output += ' EoX API not active.' + + if opt_sn2info.get('not-active') and ('sn2info' not in apistatus.keys()): + if status <= opt_sn2info.get('not-active'): + status = opt_sn2info.get('not-active') + output += ' SN2INFO API not active.' + + if opt_suggestion.get('not-active') and ('suggestion' not in apistatus.keys()): + if status <= opt_suggestion.get('not-active'): + status = opt_suggestion.get('not-active') + output += ' SUGGESTION API not active.' + else: output = 'Cisco API not active(!)' status = max(1, status) diff --git a/packages/inv_cisco_support b/packages/inv_cisco_support index 9ecfc021efa704dfd4005c9219b44fbea1908daa..64bf31ca0a5b24fd091b618b4225647a463f8190 100644 --- a/packages/inv_cisco_support +++ b/packages/inv_cisco_support @@ -30,4 +30,4 @@ 'title': u'Inventory for Cisco Bug, EoX, contract status, PSIRT advisories and suggested software', 'version': '20190830.v0.0.11', 'version.min_required': '1.4.0p1', - 'version.packaged': '1.6.0p8'} \ No newline at end of file + 'version.packaged': '1.4.0p38'} \ No newline at end of file diff --git a/web/plugins/views/inv_cisco_support.py b/web/plugins/views/inv_cisco_support.py index e07824647d167c0f2eb4857b10d46c8279cb4816..eca23a4315cf5d4bc4d4c637f2d7123d15dfab93 100644 --- a/web/plugins/views/inv_cisco_support.py +++ b/web/plugins/views/inv_cisco_support.py @@ -10,62 +10,380 @@ # (https://bst.cloudapps.cisco.com/bugsearch/bug/CSCuh91645) # +import random + + +def inv_paint_date_status(date_string): + + warn_days = -90 + crit_days = -30 + + # check if date_sting not None, if so return no CSS Class and None + if date_string is None: + return '', '' + + try: + days = int((time.time() - time.mktime(time.strptime(date_string, '%Y-%m-%d'))) / 86400) + except ValueError: + return '', date_string + + if days > crit_days: + css_class = 'date_crit' + elif days > warn_days: + css_class = 'date_warn' + else: + css_class = 'date_default' + + return css_class, '%s' % date_string + + +def inv_paint_last_checked_status(date_string): + + warn_days = 32 + crit_days = 40 + + # check if date_sting not None, if so return no CSS Class and None + if date_string is None: + return '', '' + + # check if _date_string in the right format, if not return CSS Class and date_string + try: + days = int((time.time() - time.mktime(time.strptime(date_string, '%Y-%m-%d'))) / 86400) + except ValueError: + return '', date_string + + # last_checked is ok + if days <= warn_days: + css_class = '' + # no refresh for far to long + elif days >= crit_days: + css_class = 'date_crit' + # no refresh for to long + else: + css_class = 'date_warn' + # css_class = '' + return css_class, ' %s' % date_string + + +def inv_paint_psirt_advisoryId(advisoryId): + psirt_url = '<a class="href_blue" target="_blank" href="https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/%s">%s</a>' % (advisoryId, advisoryId) + return '', psirt_url + + +def inv_paint_eox_eolid(eolid): + if eolid is not None: + search_eolid_url = '<a class="href_blue" target="_blank" href="https://search.cisco.com/search?query=%s">%s</a>' % (eolid, eolid) + else: + search_eolid_url = '' + return '', search_eolid_url + + +def render_inv_dicttable_suggestion_noqf(hostname, tree_id, invpath, node): + # In delta mode node is a pair of (old_items, new_items) + if type(node) == tuple: + html.write(_("Removed entries") + ":") + html.write("<span class=invold>") + render_inv_dicttable_suggestion_noqf(hostname, tree_id, invpath, node[0]) + html.write("</span>") + + html.write(_("New entries") + ":") + html.write("<span class=invnew>") + render_inv_dicttable_suggestion_noqf(hostname, tree_id, invpath, node[1]) + html.write("</span>") + return + + hint = inv_display_hint(invpath) + keyorder = hint.get("keyorder", []) # well known keys + + # Add titles for those keys + titles = [] + for key in keyorder: + invpath_sub = invpath + "0." + key + icon, title = inv_titleinfo(invpath_sub, None) + sub_hint = inv_display_hint(invpath_sub) + short_title = sub_hint.get("short", title) + titles.append((short_title, key)) + + # Determine *all* keys, in order to find unknown ones + keys = set([]) + for entry in node: + keys.update(entry.keys()) + + # Order not well-known keys alphabetically + extratitles = [] + for key in keys: + if key not in keyorder: + icon, title = inv_titleinfo(invpath + "0." + key, None) + extratitles.append((title, key)) + extratitles.sort() + titles += extratitles + + # Link to Multisite view with exactly this table + if "view" in hint: + url = html.makeuri_contextless([ + ("view_name", hint["view"] ), + ("host", hostname)], + filename="view.py") + html.write('<div class=invtablelink><a href="%s">%s</a></div>' % + (url, _("Open this table for filtering / sorting"))) + + # We cannot use table here, since html.plug() does not work recursively + html.write('<table class=data>') + html.write('<tr>') + for title, key in titles: + html.write('<th>%s</th>' % title) + html.write('</tr>') + + for nr, entry in enumerate(node): + html.write('<tr class=even0>') + for title, key in titles: + value = entry.get(key) + invpath_sub = invpath + "%d.%s" % (nr, key) + if type(value) == dict: + invpath_sub += "." + elif type(value) == list or (type(value) == tuple and type(value[0]) == list): + invpath_sub += ":" + + hint = inv_display_hint(invpath_sub) + if "paint_function" in hint: + td_class, text = hint["paint_function"](value) + classtext = ' class="%s"' % td_class + else: + classtext = "" + + html.write('<td%s>' % classtext) +# render_inv_subtree(hostname, tree_id, invpath_sub, value) + # render suggestions as not foldable + if key == 'suggestion' and type(value) == list: + render_inv_subtree_container(hostname, tree_id, invpath_sub, value) + else: + render_inv_subtree(hostname, tree_id, invpath_sub, value) + html.write('</td>') + html.write('</tr>') + html.write('</table>') + + +def render_inv_dicttable_suggestion(hostname, tree_id, invpath, node): + # In delta mode node is a pair of (old_items, new_items) + if type(node) == tuple: + html.write(_("Removed entries") + ":") + html.write("<span class=invold>") + render_inv_dicttable_suggestion(hostname, tree_id, invpath, node[0]) + html.write("</span>") + + html.write(_("New entries") + ":") + html.write("<span class=invnew>") + render_inv_dicttable_suggestion(hostname, tree_id, invpath, node[1]) + html.write("</span>") + return + + hint = inv_display_hint(invpath) + keyorder = hint.get("keyorder", []) # well known keys + + # Add titles for those keys + titles = [] + for key in keyorder: + invpath_sub = invpath + "0." + key + icon, title = inv_titleinfo(invpath_sub, None) + sub_hint = inv_display_hint(invpath_sub) + short_title = sub_hint.get("short", title) + titles.append((short_title, key)) + + # Determine *all* keys, in order to find unknown ones + keys = set([]) + for entry in node: + keys.update(entry.keys()) + + # Order not well-known keys alphabetically + extratitles = [] + for key in keys: + if key not in keyorder: + icon, title = inv_titleinfo(invpath + "0." + key, None) + extratitles.append((title, key)) + extratitles.sort() + titles += extratitles + + # Link to Multisite view with exactly this table + if "view" in hint: + url = html.makeuri_contextless([ + ("view_name", hint["view"] ), + ("host", hostname)], + filename="view.py") + html.write('<div class=invtablelink><a href="%s">%s</a></div>' % + (url, _("Open this table for filtering / sorting"))) + + # + # Th.L.: insert jscript for quickfilter + # + qfurl = html.makeuri([],filename="TableFilter/tablefilter.js", delvars=["host","selection","site","view_name"]) + html.write('<script language="javascript" type="text/javascript" src="%s"></script>' % qfurl) + + # Th.L.: create random table id + qf_table_id = "qf_id_" + "".join(random.SystemRandom().choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for _ in range(10)) + + # We cannot use table here, since html.plug() does not work recursively + # html.write('<table class=data>') + html.write('<table id=%s class=data>' % qf_table_id) + # html.write('<tr>') + html.write('<thead><tr>') # Th.L.: added thead for quickfilter (sort) + for title, key in titles: + html.write('<th>%s</th>' % title) + #html.write('</tr>') + html.write('</tr></thead><tbody>') # Th.L.: added thead and tbody for quickfilter (sort) + + for nr, entry in enumerate(node): + html.write('<tr class=even0>') + for title, key in titles: + value = entry.get(key) + invpath_sub = invpath + "%d.%s" % (nr, key) + if type(value) == dict: + invpath_sub += "." + elif type(value) == list or (type(value) == tuple and type(value[0]) == list): + invpath_sub += ":" + + hint = inv_display_hint(invpath_sub) + if "paint_function" in hint: + td_class, text = hint["paint_function"](value) + classtext = ' class="%s"' % td_class + else: + classtext = "" + + html.write('<td%s>' % classtext) +# render_inv_subtree(hostname, tree_id, invpath_sub, value) + # render suggestions as not foldable + if key == 'suggestion' and type(value) == list: + render_inv_subtree_container(hostname, tree_id, invpath_sub, value) + else: + render_inv_subtree(hostname, tree_id, invpath_sub, value) + html.write('</td>') + html.write('</tr>') + #html.write('</table>') + html.write('</tbody></table>') # Th.L.: added tbody for quickfilter (sort) + + # + # Th.L.: add jscript for quickfilter + # + html.write('<script data-config>\n') + html.write(' var filtersConfig = {\n') + html.write(' base_path: "TableFilter/",\n') + html.write(' alternate_rows: true,\n') + html.write(' rows_counter: true,\n') + html.write(' btn_reset: true,\n') + html.write(' bnt_reset_text: "Clear all",\n') + html.write(' loader: true,\n') + html.write(' status_bar: true,\n') + html.write(' status_bar_text : "status:",\n') + html.write(' loader : true,\n') + html.write(' mark_active_columns: true,\n') + html.write(' highlight_keywords: true,\n') + html.write(' auto_filter: true,\n') + html.write(' auto_filter_delay: 100,\n') + html.write(' paging: true,\n') + html.write(' mark_active_columns: true,\n') + html.write(' results_per_page: [" Results per page",[10,25,50,100,250,500,1000]],\n') + html.write(' no_results_message: true,\n') + html.write(' extensions:[{ name: "sort"},\n') + html.write(' { name: "colsVisibility",\n') + html.write(' tick_to_hide: false,\n') + html.write(' at_start: [11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65],\n') + html.write(' text: "Displayed columns: ",\n') + html.write(' enable_tick_all: true,\n') + html.write(' btn_html: "<button>Columns manager ▼</button>",\n') + html.write(' btn_close_html: "<button>Close</button>",\n') + html.write(' enable_hover: false,\n') + html.write(' },\n') +# html.write(' {name: "filtersVisibility"} + html.write(' ]\n') + html.write(' };\n') + html.write('\n') + html.write(' var tf = new TableFilter("%s", filtersConfig);\n' % qf_table_id) + html.write(' tf.init();\n') + html.write('\n') + html.write('</script>\n') + + +def inv_paint_bug_status(bug_status): + _bug_status = { + 'F': 'Fixed', + 'O': 'Open', + 'T': 'Terminated' + } + return '', _bug_status.get(bug_status, bug_status) + + +def inv_paint_bug_behavior_changed(behavior_changed): + _behavior_changed = { + 'Y': 'yes', + 'N': 'no', + } + return '', _behavior_changed.get(behavior_changed, behavior_changed) + + +def inv_paint_bug_bugid(bugid): + if bugid is not None: + search_bugid_url = '<a class="href_blue" target="_blank" href="https://bst.cloudapps.cisco.com/bugsearch/bug/%s">%s</a>' % (bugid, bugid) + else: + search_eolid_url = '' + return '', search_bugid_url + inventory_displayhints.update({ # EoX display hints - '.hardware.system.support.cisco_eox:': {'title': _('Cisco EoX status'), + '.hardware.support.cisco_eox:': {'title': _('Cisco EoX status'), + 'render': render_inv_dicttable, 'keyorder': ['pid', 'serial_number', 'ProductIDDescription', 'Last_checked', 'EOXExternalAnnouncementDate', 'EndOfSaleDate', 'LastDateOfSupport', 'EndOfSvcAttachDate', 'UpdatedTimeStamp', 'ProductBulletinNumber', ], -# 'view': 'invciscoeox_of_host', + 'view': 'invciscoeox_of_host', }, - '.hardware.system.support.cisco_eox:*.pid': {'title': _('PID (EoX)') }, - '.hardware.system.support.cisco_eox:*.serial_number': {'title': _('Serial number') }, - '.hardware.system.support.cisco_eox:*.ProductIDDescription': {'title': _('Description'), }, - '.hardware.system.support.cisco_eox:*.EOXExternalAnnouncementDate': {'title': _('EOL Announcement') }, - '.hardware.system.support.cisco_eox:*.EndOfSaleDate': {'title': _('End of sale') }, - '.hardware.system.support.cisco_eox:*.EndOfSvcAttachDate': {'title': _('End of service attachment') }, - '.hardware.system.support.cisco_eox:*.LastDateOfSupport': {'title': _('End of support') }, - '.hardware.system.support.cisco_eox:*.ProductBulletinNumber': {'title': _('EOL bulletin ID') }, - '.hardware.system.support.cisco_eox:*.LinkToProductBulletinURL': {'title': _('EOL bulletin URL') }, - '.hardware.system.support.cisco_eox:*.UpdatedTimeStamp': {'title': _('EOL bulletin last update') }, - '.hardware.system.support.cisco_eox:*.EndOfSecurityVulSupportDate': {'title': _('End of service vulnerability support') }, - '.hardware.system.support.cisco_eox:*.EndOfSWMaintenanceReleases': {'title': _('End of software maintenace releases') }, - '.hardware.system.support.cisco_eox:*.EndOfRoutineFailureAnalysisDate': {'title': _('End of routine failure analysis') }, - '.hardware.system.support.cisco_eox:*.MigrationProductId': {'title': _('Migration PID') }, - '.hardware.system.support.cisco_eox:*.MigrationInformation': {'title': _('Migration information') }, - '.hardware.system.support.cisco_eox:*.MigrationProductInfoURL': {'title': _('Migration PID URL') }, - '.hardware.system.support.cisco_eox:*.MigrationProductName': {'title': _('Migration product name') }, - '.hardware.system.support.cisco_eox:*.Last_checked': {'title': _('Last checked') }, + '.hardware.support.cisco_eox:*.pid': {'title': _('PID (EoX)'), }, + '.hardware.support.cisco_eox:*.serial_number': {'title': _('Serial number'), }, + '.hardware.support.cisco_eox:*.ProductIDDescription': {'title': _('Description'), }, + '.hardware.support.cisco_eox:*.EOXExternalAnnouncementDate': {'title': _('EOL Announcement'), 'paint': 'date_status', 'filter': visuals.FilterInvtableText, }, + '.hardware.support.cisco_eox:*.EndOfSaleDate': {'title': _('End of sale'), 'paint': 'date_status', 'filter': visuals.FilterInvtableText, }, + '.hardware.support.cisco_eox:*.EndOfSvcAttachDate': {'title': _('End of service attachment'), 'paint': 'date_status', 'filter': visuals.FilterInvtableText, }, + '.hardware.support.cisco_eox:*.LastDateOfSupport': {'title': _('End of support'), 'paint': 'date_status', 'filter': visuals.FilterInvtableText, }, + '.hardware.support.cisco_eox:*.ProductBulletinNumber': {'title': _('EOL bulletin ID'), 'paint': 'eox_eolid', 'filter': visuals.FilterInvtableText, }, + '.hardware.support.cisco_eox:*.LinkToProductBulletinURL': {'title': _('EOL bulletin URL'), }, + '.hardware.support.cisco_eox:*.UpdatedTimeStamp': {'title': _('EOL bulletin last update'), }, + '.hardware.support.cisco_eox:*.EndOfSecurityVulSupportDate': {'title': _('End of service vulnerability support'), 'paint': 'date_status', 'filter': visuals.FilterInvtableText, }, + '.hardware.support.cisco_eox:*.EndOfSWMaintenanceReleases': {'title': _('End of software maintenace releases'), 'paint': 'date_status', 'filter': visuals.FilterInvtableText, }, + '.hardware.support.cisco_eox:*.EndOfRoutineFailureAnalysisDate': {'title': _('End of routine failure analysis'), 'paint': 'date_status', 'filter': visuals.FilterInvtableText, }, + '.hardware.support.cisco_eox:*.MigrationProductId': {'title': _('Migration PID'), }, + '.hardware.support.cisco_eox:*.MigrationInformation': {'title': _('Migration information'), }, + '.hardware.support.cisco_eox:*.MigrationProductInfoURL': {'title': _('Migration PID URL'), }, + '.hardware.support.cisco_eox:*.MigrationProductName': {'title': _('Migration product name'), }, + '.hardware.support.cisco_eox:*.Last_checked': {'title': _('Last checked'), 'paint': 'last_checked_status', 'filter': visuals.FilterInvtableText, }, # SN2Info (contract) display hints - '.hardware.system.support.cisco_contract:': {'title': _('Cisco contract status'), + '.hardware.support.cisco_contract:': {'title': _('Cisco contract status'), + 'render': render_inv_dicttable, 'keyorder': ['pid', 'serial_number', 'ProductIDDescription', 'Last_checked', 'is_covered', 'service_contract_number', 'covered_product_line_end_date', ], -# 'view': 'invciscocontract_of_host', + 'view': 'invciscocontract_of_host', }, - '.hardware.system.support.cisco_contract:*.pid': {'title': _('PID (contract)'), }, - '.hardware.system.support.cisco_contract:*.serial_number': {'title': _('Serial number'), }, - '.hardware.system.support.cisco_contract:*.ProductIDDescription': {'title': _('Description'), }, - '.hardware.system.support.cisco_contract:*.Last_checked': {'title': _('Last checked'),}, - '.hardware.system.support.cisco_contract:*.is_covered': {'title': _('is covered'), }, - '.hardware.system.support.cisco_contract:*.contract_site_customer_name': {'title': _('Customer name'), }, - '.hardware.system.support.cisco_contract:*.contract_site_address1': {'title': _('Address'), }, - '.hardware.system.support.cisco_contract:*.contract_site_city': {'title': _('City'), }, - '.hardware.system.support.cisco_contract:*.contract_site_state_province': {'title': _('State/Province'), }, - '.hardware.system.support.cisco_contract:*.contract_site_country': {'title': _('Country'), }, - '.hardware.system.support.cisco_contract:*.service_line_descr': {'title': _('Service description'), }, - '.hardware.system.support.cisco_contract:*.service_contract_number': {'title': _('Contract number'), }, - '.hardware.system.support.cisco_contract:*.covered_product_line_end_date': {'title': _('Contract end date'),}, - '.hardware.system.support.cisco_contract:*.parent_sr_no': {'title': _('Parent S/N'), }, - '.hardware.system.support.cisco_contract:*.warranty_type': {'title': _('Warranty type'), }, - '.hardware.system.support.cisco_contract:*.warranty_type_description': {'title': _('Warranty Description'), }, - '.hardware.system.support.cisco_contract:*.warranty_end_date': {'title': _('Warranty end date'), }, + '.hardware.support.cisco_contract:*.pid': {'title': _('PID (contract)'), }, + '.hardware.support.cisco_contract:*.serial_number': {'title': _('Serial number'), }, + '.hardware.support.cisco_contract:*.ProductIDDescription': {'title': _('Description'), }, + '.hardware.support.cisco_contract:*.Last_checked': {'title': _('Last checked'), 'paint': 'last_checked_status', 'filter': visuals.FilterInvtableText,}, + '.hardware.support.cisco_contract:*.is_covered': {'title': _('is covered'), }, + '.hardware.support.cisco_contract:*.contract_site_customer_name': {'title': _('Customer name'), }, + '.hardware.support.cisco_contract:*.contract_site_address1': {'title': _('Address'), }, + '.hardware.support.cisco_contract:*.contract_site_city': {'title': _('City'), }, + '.hardware.support.cisco_contract:*.contract_site_state_province': {'title': _('State/Province'), }, + '.hardware.support.cisco_contract:*.contract_site_country': {'title': _('Country'), }, + '.hardware.support.cisco_contract:*.service_line_descr': {'title': _('Service description'), }, + '.hardware.support.cisco_contract:*.service_contract_number': {'title': _('Contract number'), }, + '.hardware.support.cisco_contract:*.covered_product_line_end_date': {'title': _('Contract end date'), 'paint': 'date_status', 'filter': visuals.FilterInvtableText,}, + '.hardware.support.cisco_contract:*.parent_sr_no': {'title': _('Parent S/N'), }, + '.hardware.support.cisco_contract:*.warranty_type': {'title': _('Warranty type'), }, + '.hardware.support.cisco_contract:*.warranty_type_description': {'title': _('Warranty Description'), }, + '.hardware.support.cisco_contract:*.warranty_end_date': {'title': _('Warranty end date'), }, # BUG display hints @@ -75,19 +393,20 @@ inventory_displayhints.update({ '.software.support.cisco_bug.PID': {'title': _('PID'), }, '.software.support.cisco_bug.os_version': {'title': _('OS version'), }, '.software.support.cisco_bug.bugs:': {'title': _('Cisco BUG IDs'), + 'render': render_inv_dicttable, 'keyorder': ['bug_id', 'last_modified_date', 'headline', 'severity', 'status', 'support_case_count', 'behavior_changed', ], -# 'view': 'invciscobugs_of_host', + 'view': 'invciscobugs_of_host', }, - '.software.support.cisco_bug.bugs:*.status': {'title': _('Status'), }, + '.software.support.cisco_bug.bugs:*.status': {'title': _('Status'), 'paint': 'bug_status', 'filter': visuals.FilterInvtableText, }, '.software.support.cisco_bug.bugs:*.product': {'title': _('Product'), }, '.software.support.cisco_bug.bugs:*.description': {'title': _('Description'), }, '.software.support.cisco_bug.bugs:*.headline': {'title': _('Headline'), }, '.software.support.cisco_bug.bugs:*.support_case_count': {'title': _('Support case count'), }, '.software.support.cisco_bug.bugs:*.last_modified_date': {'title': _('Last modified date'), }, - '.software.support.cisco_bug.bugs:*.behavior_changed': {'title': _('Behavior changed'), }, - '.software.support.cisco_bug.bugs:*.bug_id': {'title': _('Bug ID'), }, + '.software.support.cisco_bug.bugs:*.behavior_changed': {'title': _('Behavior changed'), 'paint': 'bug_behavior_changed', 'filter': visuals.FilterInvtableText, }, + '.software.support.cisco_bug.bugs:*.bug_id': {'title': _('Bug ID'), 'paint': 'bug_bugid', }, '.software.support.cisco_bug.bugs:*.base_pid': {'title': _('Base PID'), }, - '.software.support.cisco_bug.bugs:*.known_fixed_releases': {'title': _('Known fixed releases'), }, + '.software.support.cisco_bug.bugs:*.known_fixed_releases': {'title': _('Known fixed releases'), 'filter': visuals.FilterInvtableText, }, '.software.support.cisco_bug.bugs:*.id': {'title': _('ID'), }, '.software.support.cisco_bug.bugs:*.known_affected_releases': {'title': _('known affected releases'), }, '.software.support.cisco_bug.bugs:*.severity': {'title': _('Severity'), }, @@ -98,13 +417,14 @@ inventory_displayhints.update({ '.software.support.cisco_psirt.dont_show_not_updated_since': {'title': _('Don\'t show advisories not updated for X days'), }, '.software.support.cisco_psirt.removed_advisories': {'title': _('Advisories removed'), }, '.software.support.cisco_psirt.advisories:': {'title': _('Cisco PSIRT advisories'), + 'render': render_inv_dicttable, 'keyorder': ['advisoryId', 'sir', 'cvssBaseScore', 'advisoryTitle', ], -# 'view': 'invciscopsirt_of_host', + 'view': 'invciscopsirt_of_host', }, - '.software.support.cisco_psirt.advisories:*.advisoryId': {'title': _('Advisory ID'), }, + '.software.support.cisco_psirt.advisories:*.advisoryId': {'title': _('Advisory ID'), 'paint': 'psirt_advisoryId', 'filter': visuals.FilterInvtableText, }, '.software.support.cisco_psirt.advisories:*.advisoryTitle': {'title': _('Advisory Title'), }, - '.software.support.cisco_psirt.advisories:*.bugIDs': {'title': _('Bug IDs'), }, + '.software.support.cisco_psirt.advisories:*.bugIDs': {'title': _('Bug IDs'), }, # 'paint': 'psirt_bugid', 'filter': visuals.FilterInvtableText, '.software.support.cisco_psirt.advisories:*.cvssBaseScore': {'title': _('CVSS base Score'), }, '.software.support.cisco_psirt.advisories:*.firstFixed': {'title': _('First fixed in'), }, '.software.support.cisco_psirt.advisories:*.firstPublished': {'title': _('First Published'), }, @@ -120,25 +440,26 @@ inventory_displayhints.update({ '.software.support.cisco_psirt.advisories:*.cvrfUrl': {'title': _('CVRF URL'), }, '.software.support.cisco_psirt.advisories:*.ovalUrl': {'title': _('OVAL URL'), }, '.software.support.cisco_psirt.os_version': {'title': _('OS version'), }, - '.software.support.cisco_psirt.Last_checked': {'title': _('Last checked'), }, + '.software.support.cisco_psirt.Last_checked': {'title': _('Last checked'), 'paint': 'last_checked_status', 'filter': visuals.FilterInvtableText,}, '.software.support.cisco_psirt.not_updated_for_x_days': {'title': _('don\'t show advisories not updated for X days'), }, '.software.support.cisco_psirt.dont_show_older_then': {'title': _('don\'t show advisories not updated after'), }, # SUGGESTION display hints '.software.support.cisco_suggestion:': {'title': _('Cisco suggested software'), + 'render': render_inv_dicttable_suggestion, 'keyorder': ['pid', 'ProductIDDescription', 'Last_checked', ], # 'view' : 'invciscosuggestion_of_host', }, '.software.support.cisco_suggestion:*.pid': {'title': _('PID (suggestion)'), }, '.software.support.cisco_suggestion:*.ProductIDDescription': {'title': _('Description'), }, - '.software.support.cisco_suggestion:*.Last_checked': {'title': _('Last checked'), }, + '.software.support.cisco_suggestion:*.Last_checked': {'title': _('Last checked'), 'paint': 'last_checked_status', 'filter': visuals.FilterInvtableText,}, '.software.support.cisco_suggestion:*.suggestion': {'title': _('Suggestion(s)'), }, - '.software.support.cisco_suggestion:*.suggestion:': {'keyorder': ['productName', 'softwareType']}, + '.software.support.cisco_suggestion:*.suggestion:': {'render': render_inv_dicttable_suggestion_noqf, 'keyorder': ['productName', 'softwareType']}, '.software.support.cisco_suggestion:*.suggestion:*.productName': {'title': _('Product name'), }, '.software.support.cisco_suggestion:*.suggestion:*.softwareType': {'title': _('Software type'), }, '.software.support.cisco_suggestion:*.suggestion:*.suggestion': {'title': _('Suggestion(s)'), }, - '.software.support.cisco_suggestion:*.suggestion:*.suggestion:': {'keyorder': ['id', 'releaseFormat2', 'releaseDate']}, + '.software.support.cisco_suggestion:*.suggestion:*.suggestion:': {'render': render_inv_dicttable_suggestion_noqf, 'keyorder': ['id', 'releaseFormat2', 'releaseDate']}, '.software.support.cisco_suggestion:*.suggestion:*.suggestion:*.id': {'title': _('ID'), }, '.software.support.cisco_suggestion:*.suggestion:*.suggestion:*.releaseDate': {'title': _('Release date'), }, '.software.support.cisco_suggestion:*.suggestion:*.suggestion:*.releaseFormat2': {'title': _('Version'), }, @@ -152,8 +473,8 @@ inventory_displayhints.update({ }) -# declare_invtable_view('invciscoeox', '.hardware.system.support.cisco_eox:', _('Cisco EoX status'), _('Cisco EoX status')) -# declare_invtable_view('invciscocontract', '.hardware.system.support.cisco_contract:', _('Cisco contract status'), _('Cisco contract status')) -# declare_invtable_view('invciscopsirt', '.software.support.cisco_psirt.advisories:', _('Cisco PSIRT advisories'), _('Cisco PSIRT advisories')) -# declare_invtable_view('invciscobugs', '.software.support.cisco_bug.bugs:', _('Cisco BUG IDs'), _('Cisco Bug IDs')) -# declare_invtable_view('invciscosuggestion', '.software.support.cisco_suggestion:', _('Cisco suggested software'), _('Cisco suggested software')) +declare_invtable_view('invciscoeox', '.hardware.support.cisco_eox:', _('Cisco EoX status'), _('Cisco EoX status')) +declare_invtable_view('invciscocontract', '.hardware.support.cisco_contract:', _('Cisco contract status'), _('Cisco contract status')) +declare_invtable_view('invciscopsirt', '.software.support.cisco_psirt.advisories:', _('Cisco PSIRT advisories'), _('Cisco PSIRT advisories')) +declare_invtable_view('invciscobugs', '.software.support.cisco_bug.bugs:', _('Cisco BUG IDs'), _('Cisco Bug IDs')) +#declare_invtable_view('invciscosuggestion', '.software.support.cisco_suggestion:', _('Cisco suggested software'), _('Cisco suggested software'))