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 &#9660;</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'))