From 18ef13ea39f8a707f42e8e5df91315222e47e00a Mon Sep 17 00:00:00 2001
From: "th.l" <thl-cmk@outlook.com>
Date: Sat, 15 Jun 2024 14:01:08 +0200
Subject: [PATCH] update project

---
 {doc => img}/sample_bug.png                   | Bin
 {doc => img}/sample_contract.png              | Bin
 {doc => img}/sample_eox.png                   | Bin
 {doc => img}/sample_psirt.png                 | Bin
 mkp/inv_cisco_support-0.3.0-20231025.mkp      | Bin 24992 -> 24998 bytes
 .../agent_based}/inv_cisco_bug.py             |   0
 .../agent_based}/inv_cisco_contract.py        |   0
 .../agent_based}/inv_cisco_eox.py             |   0
 .../agent_based}/inv_cisco_psirt.py           |   0
 .../agent_based}/utils/inv_cisco_support.py   |   0
 source/bin/ciscoapi/cisco-bug.py              | 275 +++++++++
 source/bin/ciscoapi/cisco-eox.py              | 218 ++++++++
 source/bin/ciscoapi/cisco-psirt.py            | 187 +++++++
 source/bin/ciscoapi/cisco-sn2info.py          | 120 ++++
 source/bin/ciscoapi/cisco_live_cycle_utils.py | 202 +++++++
 source/bin/ciscoapi/ciscoapi.py               | 521 ++++++++++++++++++
 .../gui}/views/inv_cisco_livecycle.py         |   0
 {gui => source/gui}/wato/inv_cisco_bug.py     |   0
 .../gui}/wato/inv_cisco_contract.py           |   0
 {gui => source/gui}/wato/inv_cisco_eox.py     |   0
 {gui => source/gui}/wato/inv_cisco_psirt.py   |   0
 .../packages}/inv_cisco_support               |   2 +-
 .../web}/htdocs/css/inv_cisco_support.css     |   0
 23 files changed, 1524 insertions(+), 1 deletion(-)
 rename {doc => img}/sample_bug.png (100%)
 rename {doc => img}/sample_contract.png (100%)
 rename {doc => img}/sample_eox.png (100%)
 rename {doc => img}/sample_psirt.png (100%)
 rename {agent_based => source/agent_based}/inv_cisco_bug.py (100%)
 rename {agent_based => source/agent_based}/inv_cisco_contract.py (100%)
 rename {agent_based => source/agent_based}/inv_cisco_eox.py (100%)
 rename {agent_based => source/agent_based}/inv_cisco_psirt.py (100%)
 rename {agent_based => source/agent_based}/utils/inv_cisco_support.py (100%)
 create mode 100755 source/bin/ciscoapi/cisco-bug.py
 create mode 100755 source/bin/ciscoapi/cisco-eox.py
 create mode 100755 source/bin/ciscoapi/cisco-psirt.py
 create mode 100755 source/bin/ciscoapi/cisco-sn2info.py
 create mode 100755 source/bin/ciscoapi/cisco_live_cycle_utils.py
 create mode 100755 source/bin/ciscoapi/ciscoapi.py
 rename {gui => source/gui}/views/inv_cisco_livecycle.py (100%)
 rename {gui => source/gui}/wato/inv_cisco_bug.py (100%)
 rename {gui => source/gui}/wato/inv_cisco_contract.py (100%)
 rename {gui => source/gui}/wato/inv_cisco_eox.py (100%)
 rename {gui => source/gui}/wato/inv_cisco_psirt.py (100%)
 rename {packages => source/packages}/inv_cisco_support (98%)
 rename {web => source/web}/htdocs/css/inv_cisco_support.css (100%)

diff --git a/doc/sample_bug.png b/img/sample_bug.png
similarity index 100%
rename from doc/sample_bug.png
rename to img/sample_bug.png
diff --git a/doc/sample_contract.png b/img/sample_contract.png
similarity index 100%
rename from doc/sample_contract.png
rename to img/sample_contract.png
diff --git a/doc/sample_eox.png b/img/sample_eox.png
similarity index 100%
rename from doc/sample_eox.png
rename to img/sample_eox.png
diff --git a/doc/sample_psirt.png b/img/sample_psirt.png
similarity index 100%
rename from doc/sample_psirt.png
rename to img/sample_psirt.png
diff --git a/mkp/inv_cisco_support-0.3.0-20231025.mkp b/mkp/inv_cisco_support-0.3.0-20231025.mkp
index 8b6b4a2aaef9fa571f1ba56e0765b696a2329f77..5f2bc5d6ebc0a74a8f9d442d8dc4a166b6f0c8a2 100644
GIT binary patch
delta 23306
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
ZlW<`qlb}un4c~V9{{cbmGwuM;0sz-0vjPAB

delta 23306
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
ZD3iTT3zNN02@G#L{r_r1yJ`T?0suAJizNU6

diff --git a/agent_based/inv_cisco_bug.py b/source/agent_based/inv_cisco_bug.py
similarity index 100%
rename from agent_based/inv_cisco_bug.py
rename to source/agent_based/inv_cisco_bug.py
diff --git a/agent_based/inv_cisco_contract.py b/source/agent_based/inv_cisco_contract.py
similarity index 100%
rename from agent_based/inv_cisco_contract.py
rename to source/agent_based/inv_cisco_contract.py
diff --git a/agent_based/inv_cisco_eox.py b/source/agent_based/inv_cisco_eox.py
similarity index 100%
rename from agent_based/inv_cisco_eox.py
rename to source/agent_based/inv_cisco_eox.py
diff --git a/agent_based/inv_cisco_psirt.py b/source/agent_based/inv_cisco_psirt.py
similarity index 100%
rename from agent_based/inv_cisco_psirt.py
rename to source/agent_based/inv_cisco_psirt.py
diff --git a/agent_based/utils/inv_cisco_support.py b/source/agent_based/utils/inv_cisco_support.py
similarity index 100%
rename from agent_based/utils/inv_cisco_support.py
rename to source/agent_based/utils/inv_cisco_support.py
diff --git a/source/bin/ciscoapi/cisco-bug.py b/source/bin/ciscoapi/cisco-bug.py
new file mode 100755
index 0000000..bca0cb3
--- /dev/null
+++ b/source/bin/ciscoapi/cisco-bug.py
@@ -0,0 +1,275 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2018-01-25
+#
+# add on for cisco support api. calls cisco bug api 2.0.
+# for more information see: https://developer.cisco.com/docs/support-apis/#bug
+#
+# 2021-07-24: rewrite for python3.8
+#
+import os
+import json
+
+from cisco_live_cycle_utils import (
+    configure_logger,
+    log_message,
+    expand_path,
+    get_ids_from_dir,
+    get_subdirs_from_dir,
+    remove_empty_sub_dirs,
+    sleep_random,
+    move_dir,
+)
+from ciscoapi import (
+    AccessToken,
+    Settings,
+    get_bug_by_pid_and_release,
+)
+
+
+def main():
+    settings = Settings()
+    access_token = AccessToken(settings.client_id, settings.client_secret, settings.proxies)
+    configure_logger(log_level=settings.log_level)
+
+    bug_path = settings.base_path + '/bug'
+    path_found = expand_path(bug_path + '/found')
+    path_not_found = expand_path(bug_path + '/not_found')
+    path_request = expand_path(bug_path + '/request')
+    path_missing = expand_path(bug_path + '/missing')
+
+    pids_requested = {}
+    pids_refresh = {}
+
+    # get list of bug reports to refresh
+    pids = get_subdirs_from_dir(path_found)
+    for pid in pids:
+        pids_refresh[pid.replace('_', '/')] = ','.join(get_ids_from_dir(path_found+pid,
+                                                                        refresh_time=settings.bug_refresh_found))
+
+    # move not_found bug reports older then 'refresh_notfound' days to request (for refresh)
+    move_dir(path_not_found, path_request, refresh_time=settings.bug_refresh_not_found)
+
+    # get list of PIDs requests
+    pids = get_subdirs_from_dir(path_request)
+    log_message(f'bug requests (PIDs): {pids}')
+    for pid in pids:
+        pids_requested[pid.replace('_', '/')] = ','.join(get_ids_from_dir(path_request+pid))
+    log_message(f'bug requests (PIDs and releases): {pids_requested}')
+
+    if len(pids_refresh.keys()) > 0 or len(pids_requested.keys()) > 0:
+
+        reqoptions = []
+
+        # modified_date
+        # 1 = Last Week
+        # 2 = Last 30 Days(default)
+        # 3 = Last 6  Months
+        # 4 = Last Year
+        # 5 = All
+        reqoptions.append('modified_date=1')
+#        reqoptions.append('modified_date=3')  # for testing
+
+        # severity (default is all)
+        # 1 = Severity 1
+        # 2 = Severity 2
+        # 3 = Severity 3
+        # 4 = Severity 4
+        # 5 = Severity 5
+        # 6 = Severity 6
+        # reqoptions.append('severity=2')
+
+        # status (default is all)
+        # O = Open
+        # F = Fixed
+        # T = Terminated
+        # reqoptions.append('status=O')
+
+        # sort_by
+        #  status
+        #  modified_date (recent first, default)
+        #  severity
+        #  support_case_count
+        #  modified_date_earliest (earliest first)
+        # reqoptions.append('sort_by=severity')
+
+        # reqoptions.append('page_index=2')
+
+        if len(reqoptions) > 0:
+            reqoptions = '?' + '&'.join(reqoptions)
+        else:
+            reqoptions = ''
+
+        # wait random time after startup (load spread)
+        if settings.wait_after_start:
+            sleep_random(settings.max_wait_time)
+
+        # first refresh bug reports
+        for pid in pids_refresh.keys():
+
+            # get bug records for time frame
+            bug_records = get_bug_by_pid_and_release(
+                pid,
+                pids_refresh.get(pid),
+                access_token,
+                reqoptions,
+                settings=settings
+            )
+            for entry in bug_records:
+                pid = entry.get('pid')
+                software_releases = entry.get('software_releases')
+                status_code = int(entry.get('status_code', 200))
+                log_message(f'bug return:PID: {pid}, Status: {status_code}, Version: {software_releases}')
+                path = expand_path(path_found + pid.replace('/', '_'))
+                # check if there were was an error, if so go to next pid
+                if status_code == 200:
+                    bugs = entry.get('bugs', None)
+                    if bugs:  # if new/changed bugs found
+                        for bug in bugs:
+                            bug.pop('description')  # remove description
+                        for release in software_releases.keys():  # create one bug list per software release
+                            bug_release = software_releases.get(release)
+                            log_message(f'bug found:PID: {pid}, Releases: {release}')
+                            new_bugs = []
+                            for bug in bugs:
+                                if bug_release in bug.get('known_affected_releases'):
+                                    new_bugs.append(bug)
+
+                            # open found file
+                            with open(path + release) as f:
+                                try:
+                                    bug_record = json.load(f)
+                                except ValueError as e:
+                                    log_message(f'{pid}:{release}:snmp_cisco_bug:bug_found:JSON load error: {e}',
+                                                level='WARNING')
+
+                            found_bugs = bug_record.get('bugs')
+                            for found_bug in found_bugs:
+                                for new_bug in new_bugs:
+                                    if found_bug.get('bug_id') == new_bug.get('bug_id'):
+                                        found_bug.update(new_bug)  # update old bug with new data (changed bugs)
+                                        new_bugs.remove(new_bug)
+                            for bug in new_bugs:
+                                found_bugs.append(bug)  # add new bugs
+                            bug_record['bugs'] = found_bugs  # replace bug list with new list
+                            bug_record['total_records'] = len(found_bugs)  # change number of records
+
+                            with open(path + release, 'w') as f:
+                                json.dump(bug_record, f)  # write updated bug report
+
+                    else:
+                        for release in software_releases.keys():
+                            if os.path.exists(path + release):
+                                os.utime(path + release, None)
+
+        reqoptions = []
+
+        # modified_date
+        # 1 = Last Week
+        # 2 = Last 30 Days(default)
+        # 3 = Last 6  Months
+        # 4 = Last Year
+        # 5 = All
+        reqoptions.append('modified_date=5')
+#        reqoptions.append('modified_date=2')  # for testing
+
+        # severity (default is all)
+        # 1 = Severity 1
+        # 2 = Severity 2
+        # 3 = Severity 3
+        # 4 = Severity 4
+        # 5 = Severity 5
+        # 6 = Severity 6
+        # reqoptions.append('severity=2')
+
+        # status (default is all)
+        # O = Open
+        # F = Fixed
+        # T = Terminated
+        # reqoptions.append('status=O')
+
+        # sort_by
+        #  status
+        #  modified_date (recent first, default)
+        #  severity
+        #  support_case_count
+        #  modified_date_earliest (earliest first)
+        # reqoptions.append('sort_by=severity')
+
+        # reqoptions.append('page_index=2')
+
+        if len(reqoptions) > 0:
+            reqoptions = '?' + '&'.join(reqoptions)
+        else:
+            reqoptions = ''
+
+        for pid in pids_requested.keys():
+            bug_records = get_bug_by_pid_and_release(
+                pid,
+                pids_requested.get(pid),
+                access_token,
+                reqoptions,
+                settings=settings
+            )
+            for entry in bug_records:
+                pid = entry.get('pid')
+                software_releases = entry.get('software_releases')
+                status_code = int(entry.get('status_code', 200))
+                log_message(f'bug return:PID: {pid}, Status: {status_code}, Version: {software_releases}')
+                # check if there where was an error, if so go to next pid
+                if status_code == 200:
+                    bugs = entry.get('bugs', None)
+                    if bugs:
+                        for bug in bugs:
+                            bug.pop('description')
+                    for release in software_releases.keys():  # create one bug list per software release
+                        bug_release = software_releases.get(release)
+                        if bugs:
+                            log_message(f'bug found:PID: %s{pid}, Releases: {release}')
+                            missing = entry.get('missing', {})
+                            # split bugs by release
+                            release_bugs = {
+                                'pid': pid,
+                                'software_release': release,
+                                'bugs': [],
+                                'missing': missing
+                            }
+                            for bug in bugs:
+                                if bug_release in bug.get('known_affected_releases'):
+                                    release_bugs['bugs'].append(bug)
+                            release_bugs['total_records'] = len(release_bugs['bugs'])
+
+                            path = expand_path(path_found + pid.replace('/', '_'))
+                            with open(path + release, 'w') as f:
+                                json.dump(release_bugs, f)
+
+                            if len(missing.keys()) != 0:
+                                path = expand_path(path_missing + pid.replace('/', '_'))
+                                with open(path + release, 'w') as f:
+                                    json.dump(missing, f)
+                        else:
+                            log_message(f'bug not found:PID: {pid}, Version: {release}')
+                            path = expand_path(path_not_found + pid.replace('/', '_'))
+                            log_message(f'not found: {entry}')
+                            with open(path + release, 'w') as f:
+                                json.dump(entry, f)
+                                pass
+
+                        # remove request file
+                        try:
+                            log_message(f'bug delete request:PID: {pid}, Version: {release}')
+                            os.remove(path_request + pid.replace('/', '_') + '/' + release)
+                        except OSError:
+                            pass
+
+        # clean up (remove empty directories)
+        remove_empty_sub_dirs(path_request)
+        remove_empty_sub_dirs(path_found)
+        remove_empty_sub_dirs(path_not_found)
+        remove_empty_sub_dirs(path_missing)
+
+
+main()
diff --git a/source/bin/ciscoapi/cisco-eox.py b/source/bin/ciscoapi/cisco-eox.py
new file mode 100755
index 0000000..cfcc556
--- /dev/null
+++ b/source/bin/ciscoapi/cisco-eox.py
@@ -0,0 +1,218 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2017-05-15
+#
+#  https://developer.cisco.com/docs/support-apis/
+#
+# 2021-07-23: rewrite for python 3.8
+#
+import json
+from cisco_live_cycle_utils import (
+    configure_logger,
+    log_message,
+    expand_path,
+    get_ids_from_dir,
+    remove_ids_from_list,
+    refresh_ids_from_dir,
+    remove_ids_from_dir,
+    sleep_random,
+)
+from ciscoapi import (
+    AccessToken,
+    Settings,
+    get_eox_by_pid,
+    get_eox_by_serials,
+)
+
+
+# split pids in known and unknown eox state
+def split_pids(eoxr):
+    eox_known = []
+    eox_unkown = []
+
+    for response in eoxr:
+        EOXRecord = response.get('EOXRecord')
+        #        PaginationResponseRecord = response.get('PaginationResponseRecord')
+        #        PageIndex = PaginationResponseRecord.get('PageIndex')
+        #        LastIndex = PaginationResponseRecord.get('LastIndex')
+        #        PageRecords = PaginationResponseRecord.get('PageRecords')
+        #        TotalRecords = PaginationResponseRecord.get('TotalRecords')
+        if EOXRecord is not None:
+            for PID in EOXRecord:
+                if PID.get('EOLProductID') != '':
+                    eox_known.append(PID)
+                    log_message(message=f'EOLProductID  : {PID.get("EOLProductID")}')
+                else:
+                    eox_unkown.append(PID)
+                    log_message(f'EOXInputValue : {PID.get("EOXInputValue")}')
+    return {'eox_known': eox_known, 'eox_unknown': eox_unkown}
+
+
+# split serials, expects a list of EoX Records from get EoX by serial
+def split_serials(eoxr):
+    serials = []
+
+    for PID in eoxr:
+        EOLProductID = PID.get('EOLProductID')
+        log_message(f'serial split Eox: found PID: {EOLProductID}')
+        EOXInputValue = PID.get('EOXInputValue').split(',')
+        for serial in EOXInputValue:
+            log_message(f'found Serial: {serial}')
+            eox_serial = PID.copy()
+            eox_serial.update({'EOXInputValue': serial})
+            serials.append(eox_serial)
+            log_message(f'Serial EoX: {eox_serial}')
+
+    return serials
+
+
+# save EoX records to file by PID,
+# expects a list of EoX Records from Cisco EoX API 5.0,
+# returns a list of saved PIDs
+def save_eox(eox, path):
+    saved = []
+
+    for PID in eox:
+        EOLProductID = PID.get('EOLProductID')
+        # EOLProductID is empty for EoX Records with unknown EoX state (error or not announced)
+        if EOLProductID == '':
+            EOLProductID = PID.get('EOXInputValue')
+
+        if EOLProductID:
+            with open(path + (EOLProductID.replace('/', '_')), 'w') as f:
+                json.dump(PID, f)
+                saved.append(EOLProductID)
+
+    return saved
+
+
+def save_serials(eox, path):
+    """
+    Saves EoX records to file by serial number.
+    Args:
+        eox: List of EoX Records from Cisco EoX API 5.0
+        path: file path where to save the EoX records
+
+    Returns: List of serial numbers of saved EoX records
+
+    """
+
+    saved = []
+
+    for serial in eox:
+        EOXInputValue = serial.get('EOXInputValue')
+        if EOXInputValue:
+            with open(path + EOXInputValue, 'w') as f:
+                json.dump(serial, f)
+            saved.append(EOXInputValue)
+
+    return saved
+
+
+def main():
+    settings = Settings()
+    access_token = AccessToken(settings.client_id, settings.client_secret, settings.proxies)
+    configure_logger(log_level=settings.log_level)
+
+    eox_path = settings.base_path + '/EoX'
+    path_found = eox_path + '/found'
+    path_not_found = eox_path + '/not_found'
+    path_request = eox_path + '/request'
+
+    path_request_pid = expand_path(path_request + '/pid')
+    path_found_pid = expand_path(path_found + '/pid')
+    path_not_found_pid = expand_path(path_not_found + '/pid')
+
+    path_request_ser = expand_path(path_request + '/ser')
+    path_found_ser = expand_path(path_found + '/ser')
+    path_not_found_ser = expand_path(path_not_found + '/ser')
+
+    # create list of PIDs to request EoX status for
+    pids = get_ids_from_dir(path_request_pid)
+    log_message(f'pid requests : {pids}')
+    # remove already known PIDs from list
+    pids = remove_ids_from_list(pids, path_found_pid)
+    log_message(f'pid requests : {pids}')
+    # remove PIDs already requested with unknown EoX status from list
+    pids = remove_ids_from_list(pids, path_not_found_pid)
+    log_message(f'pid requests : {pids}')
+
+    # refresh PIDs after 30 days by default
+    pids = refresh_ids_from_dir(path_not_found_pid, settings.eox_refresh_unknown, pids, True)
+    log_message(f'pid requests : {pids}')
+    pids = refresh_ids_from_dir(path_found_pid, settings.eox_refresh_known, pids, False)
+    log_message(f'pid requests : {pids}')
+
+    # create list of serial numbers to request EoX status for
+    serials = get_ids_from_dir(path_request_ser)
+    log_message(f'ser requests : {serials}')
+    # remove already known serials from list
+    serials = remove_ids_from_list(serials, path_found_ser)
+    log_message(f'ser requests : {serials}')
+    # remove serials already requested with unknown EoX status from list
+    serials = remove_ids_from_list(serials, path_not_found_ser)
+    log_message(f'ser requests : {serials}')
+
+    # refresh serials after 30 days by default
+    serials = refresh_ids_from_dir(path_not_found_ser, settings.eox_refresh_unknown, serials, True)
+    log_message(f'ser requests : {serials}')
+    serials = refresh_ids_from_dir(path_found_ser, settings.eox_refresh_known, serials, False)
+    log_message(f'ser requests : {serials}')
+
+    if pids == [] and serials == []:
+        log_message('all list are empty. Do nothing.')
+        return
+
+    # wait random time after startup (load spread)
+    if settings.wait_after_start:
+        sleep_random(settings.max_wait_time)
+
+    if pids is not []:
+        eox = get_eox_by_pid(pids=pids, access_token=access_token, settings=settings)
+
+        # split eox records in a list of known and unknown pid records
+        eox = split_pids(eox)
+
+        # save known pid reports
+        pids = save_eox(eox.get('eox_known'), path_found_pid)
+        # delete requests for known pids
+        remove_ids_from_dir(pids, path_request_pid)
+
+        # save unknown pid reports
+        pids = save_eox(eox.get('eox_unknown'), path_not_found_pid)
+        # delete requests for unknown pids
+        remove_ids_from_dir(pids, path_request_pid)
+        # delete pids from known were the status changed to unknown
+        remove_ids_from_dir(pids, path_found_pid)
+
+    if serials is not []:
+        eox = get_eox_by_serials(serials=serials, access_token=access_token, settings=settings)
+        log_message(f'eox by ser: {eox}')
+
+        # split eox records in a list of known and unknown pid records
+        eox = split_pids(eox)
+
+        # split EoX records for known PIDs in one entry per serial
+        serials = split_serials(eox.get('eox_known'))
+        # save EoX records for serials with known EoX state
+        serials = save_serials(serials, path_found_ser)
+        log_message(f'EoX Serials: known: {serials}')
+        # delete requests for known serials
+        remove_ids_from_dir(serials, path_request_ser)
+
+        # split EoX records for unknown PIDs in one entry per serial
+        serials = split_serials(eox.get('eox_unknown'))
+        # save EoX records for serials with known EoX state
+        serials = save_serials(serials, path_not_found_ser)
+        # delete requests for unknown serials
+        remove_ids_from_dir(serials, path_request_ser)
+        # delete serials from known were the status changed to unknown
+        remove_ids_from_dir(serials, path_found_ser)
+
+
+main()
diff --git a/source/bin/ciscoapi/cisco-psirt.py b/source/bin/ciscoapi/cisco-psirt.py
new file mode 100755
index 0000000..876d50c
--- /dev/null
+++ b/source/bin/ciscoapi/cisco-psirt.py
@@ -0,0 +1,187 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2017-07-10
+#
+#  https://developer.cisco.com/docs/support-apis/
+#
+# 2018-06-06: fixed handling if state changes form found to not_found (delete old psirt found file)
+# 2021-07-24: rewritten for python 3.8
+#
+#
+import ntpath
+import os
+import json
+from typing import List
+from dataclasses import dataclass
+
+from cisco_live_cycle_utils import (
+    configure_logger,
+    log_message,
+    get_ids_from_dir,
+    remove_ids_from_list,
+    refresh_ids_from_dir,
+    sleep_random,
+    expand_path,
+)
+from ciscoapi import (
+    AccessToken,
+    Settings,
+    get_psirt_by_product_family,
+    get_psirt_by_iosxe_version,
+    get_psirt_by_ios_version,
+)
+
+
+@dataclass
+class Paths:
+    found: str
+    not_found: str
+    request: str
+
+
+@dataclass
+class Refresh:
+    found: int
+    not_found: int
+
+
+g_logger = None
+
+
+def _psirt_remove_id_file(psirt_path: str, psirt_id: str):
+    # delete psirt file
+    try:
+        log_message(f'delete psirt id file : {psirt_path + psirt_id}')
+        os.remove(psirt_path + psirt_id)
+    except OSError:
+        pass
+
+
+def _psirt_dump_record(psirt_record, psirt_id: str, psirt_path: str, psirt_path_request: str):
+    with open(psirt_path + psirt_id, 'w') as f:
+        json.dump(psirt_record, f)
+    # delete request file
+    _psirt_remove_id_file(psirt_path_request, psirt_id)
+
+    return
+
+
+def _check_psirt_record(psirt_record, psirt_id, psirt_path_found, psirt_path_request):
+    """
+
+    :param psirt_record:
+    :param psirt_id:
+    :param psirt_path_found:
+    :param psirt_path_request:
+    :returns:
+    """
+
+    for advisory in psirt_record.get('advisories'):
+        # remove unwanted information from advisories
+        advisory.pop('productNames', None)
+        advisory.pop('ipsSignatures', None)
+        advisory.pop('iosRelease', None)
+        advisory.pop('cvrfUrl', None)
+        advisory.pop('ovalUrl', None)
+        advisory.pop('summary', None)
+        temp_advisory = advisory.copy()
+        for key in temp_advisory.keys():
+            if advisory.get(key, None) in [['NA'], 'NA']:
+                advisory.pop(key, None)
+
+    _psirt_dump_record(psirt_record, psirt_id, psirt_path_found, psirt_path_request)
+
+    return
+
+
+def _get_psirt_id_list(product_family: str, paths: Paths, refresh: Refresh) -> List[str]:
+    """
+
+    @param product_family:
+    @param paths: Path object with path to founnd/not found/requested PSIRT records
+    @param refresh: Refresh object with number of days before a PSIRT record needs to be refreshed for found/not found
+    @return: list of PIDs
+    """
+    # create list of ID's to request PSIRT status for
+    psirt_id_list = get_ids_from_dir(paths.request + product_family)
+    log_message(f'psirt requests : {psirt_id_list}')
+    # remove already found ID's from list
+    psirt_id_list = remove_ids_from_list(psirt_id_list, paths.found + product_family)
+    log_message(f'psirt requests : {psirt_id_list}')
+    # remove not found ID's from list
+    psirt_id_list = remove_ids_from_list(psirt_id_list, paths.not_found + product_family)
+    log_message(f'psirt requests : {psirt_id_list}')
+
+    # refresh psirt after 1 day by default
+    psirt_id_list = refresh_ids_from_dir(paths.not_found + product_family, refresh.not_found, psirt_id_list, True)
+    log_message(f'psirt requests : {psirt_id_list}')
+    psirt_id_list = refresh_ids_from_dir(paths.found + product_family, refresh.found, psirt_id_list, False)
+    log_message(f'psirt requests : {psirt_id_list}')
+
+    return psirt_id_list
+
+
+def _update_psirt_id(psirt_records: list, family_name: str, paths: Paths):
+    for psirt_record in psirt_records:
+        if family_name in ['IOS', 'IOS-XE']:
+            psirt_id = psirt_record.get('version')
+        else:
+            psirt_id = psirt_record.get('family')
+
+        if psirt_record.get('advisories') != 'notfound':
+            _check_psirt_record(psirt_record, psirt_id, paths.found + family_name + '/',
+                                ntpath.sep + family_name + '/')
+        else:
+            _psirt_dump_record(psirt_record, psirt_id, paths.not_found + family_name + '/',
+                               paths.request + family_name + '/')
+            # remove psirt_found file (happens when product family is removed form bug ID)
+            _psirt_remove_id_file(paths.found + family_name + '/', psirt_id)
+    return
+
+
+def main():
+    settings = Settings()
+    access_token = AccessToken(settings.client_id, settings.client_secret, settings.proxies)
+    configure_logger(log_level=settings.log_level)
+
+    refresh = Refresh(
+        found=settings.psirt_refresh_found,
+        not_found=settings.psirt_refresh_not_found
+    )
+
+    psirt_dir = expand_path(settings.base_path + '/psirt')
+    paths = Paths(
+        found=psirt_dir + '/found/',
+        not_found=psirt_dir + '/not_found/',
+        request=psirt_dir + '/request/'
+    )
+
+    psirt_ios = _get_psirt_id_list('IOS', paths, refresh)
+    psirt_ios_xe = _get_psirt_id_list('IOS-XE', paths, refresh)
+    psirt_family = _get_psirt_id_list('family', paths, refresh)
+
+    if (psirt_ios == []) and psirt_ios_xe == [] and psirt_family == []:
+        log_message('all list are empty. Do nothing.')
+        return
+
+    # wait random time after startup
+    if settings.wait_after_start:
+        sleep_random(settings.max_wait_time)
+
+    if psirt_family is not []:
+        psirt_records = get_psirt_by_product_family(psirt_family, access_token, settings=settings)
+        _update_psirt_id(psirt_records, 'family', paths)
+
+    if psirt_ios_xe is not []:
+        psirt_records = get_psirt_by_iosxe_version(psirt_ios_xe, access_token, settings=settings)
+        _update_psirt_id(psirt_records, 'IOS-XE', paths)
+
+    if psirt_ios is not []:
+        psirt_records = get_psirt_by_ios_version(psirt_ios, access_token, settings=settings)
+        _update_psirt_id(psirt_records, 'IOS', paths)
+
+
+main()
diff --git a/source/bin/ciscoapi/cisco-sn2info.py b/source/bin/ciscoapi/cisco-sn2info.py
new file mode 100755
index 0000000..6521bd5
--- /dev/null
+++ b/source/bin/ciscoapi/cisco-sn2info.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2017-04-15:
+#
+# Cisco SN2INFO API Framework
+#
+# https://developer.cisco.com/docs/support-apis/#serial-number-to-information
+#
+# 2021-07-23: rewrite for python 3.8
+#
+import json
+
+from cisco_live_cycle_utils import (
+    configure_logger,
+    log_message,
+    expand_path,
+    get_ids_from_dir,
+    remove_ids_from_list,
+    refresh_ids_from_dir,
+    remove_ids_from_dir,
+    sleep_random,
+)
+from ciscoapi import (
+    AccessToken,
+    Settings,
+    get_coverage_summary_by_serials,
+)
+
+
+def sn2info_split_covered(sn2info_records):
+    sn2info_covered = []
+    sn2info_notcovered = []
+
+    for response in sn2info_records:
+        sn2inforecord = response.get('serial_numbers')
+#        PaginationResponseRecord = response.get('PaginationResponseRecord')
+#        PageIndex = PaginationResponseRecord.get('PageIndex')
+#        LastIndex = PaginationResponseRecord.get('LastIndex')
+#        PageRecords = PaginationResponseRecord.get('PageRecords')
+#        TotalRecords = PaginationResponseRecord.get('TotalRecords')
+        if sn2inforecord is not None:
+            for serial in sn2inforecord:
+                if serial.get('is_covered') == 'YES':
+                    sn2info_covered.append(serial)
+                    log_message(f'SN2INFO covered  : {serial.get("sr_no")}')
+                else:
+                    sn2info_notcovered.append(serial)
+                    log_message(f'SN2INFO not covered : {serial.get("sr_no")}')
+    return {'sn2info_covered': sn2info_covered, 'sn2info_notcovered': sn2info_notcovered}
+
+
+def sn2info_save_serials(sn2infos, path):
+    saved = []
+
+    for sn2info in sn2infos:
+        serial = str(sn2info.get('sr_no'))
+        if serial:
+            with open(path + serial, 'w') as f:
+                json.dump(sn2info, f)
+            saved.append(serial)
+
+    return saved
+
+
+def main():
+    settings = Settings()
+    access_token = AccessToken(settings.client_id, settings.client_secret, settings.proxies)
+    configure_logger(log_level=settings.log_level)
+
+    sn2info_dir = settings.base_path + '/sn2info'
+    path_found = expand_path(sn2info_dir + '/found/')
+    path_not_found = expand_path(sn2info_dir + '/not_found/')
+    path_request = expand_path(sn2info_dir + '/request/')
+
+    # create list of serial numbers to request SN2INFO status for
+    sn2info = get_ids_from_dir(path_request)
+    log_message(f'sn2info requests : {sn2info}')
+    # remove covered serials from list
+    sn2info = remove_ids_from_list(sn2info, path_found)
+    log_message(f'sn2info requests : {sn2info}')
+    # remove not covered serials from list
+    sn2info = remove_ids_from_list(sn2info, path_not_found)
+    log_message(f'sn2info requests : {sn2info}')
+
+    # refresh sn2info serials after 31 days by default
+    sn2info = refresh_ids_from_dir(path_not_found, settings.sn2info_refresh_not_covered, sn2info, True)
+    log_message(f'sn2info requests : {sn2info}')
+    sn2info = refresh_ids_from_dir(path_found, settings.sn2info_refresh_covered, sn2info, False)
+    log_message(f'sn2info requests : {sn2info}')
+
+    if sn2info is []:
+        log_message('all list are empty. Do nothing.')
+        return
+
+    # wait random time after startup
+    if settings.wait_after_start:
+        sleep_random(settings.max_wait_time)
+
+    if sn2info is not []:
+        sn2info_records = get_coverage_summary_by_serials(
+            serials=sn2info,
+            access_token=access_token,
+            settings=settings
+        )
+        log_message(f'sn2info response: {sn2info_records}')
+        sn2info = sn2info_split_covered(sn2info_records)
+        serials = sn2info_save_serials(sn2info.get('sn2info_covered'), path_found)
+        remove_ids_from_dir(serials, path_request)
+        serials = sn2info_save_serials(sn2info.get('sn2info_notcovered'), path_not_found)
+        remove_ids_from_dir(serials, path_request)
+        # delete serials from covered were the status changed to uncovered
+        remove_ids_from_dir(serials, path_found)
+
+
+main()
diff --git a/source/bin/ciscoapi/cisco_live_cycle_utils.py b/source/bin/ciscoapi/cisco_live_cycle_utils.py
new file mode 100755
index 0000000..17dc773
--- /dev/null
+++ b/source/bin/ciscoapi/cisco_live_cycle_utils.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+
+#
+# 15.04.2017 : Th.L. : Support for Cisco API
+#
+#  https://developer.cisco.com/docs/support-apis/
+#
+
+import logging
+import os
+import time
+import random
+import sys
+
+
+def configure_logger(_path: str = '', _log_to_console: bool = True, log_level: str = 'INFO'):
+    log_formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(name)s :: %(module)s ::%(message)s')
+    log = logging.getLogger('root')
+
+    numeric_level = getattr(logging, log_level.upper(), None)
+    if isinstance(numeric_level, int):
+        logging.getLogger().setLevel(numeric_level)
+    else:
+        logging.getLogger().setLevel(logging.WARNING)
+
+    log_handler_console = logging.StreamHandler(sys.stdout)
+    log_handler_console.setFormatter(log_formatter)
+    log_handler_console.setLevel(logging.INFO)
+    log.addHandler(log_handler_console)
+
+
+def log_message(message: str, level: str = 'DEBUG'):
+    log = logging.getLogger()
+    if level.upper() == 'CRITICAL':
+        log.critical(message)
+    elif level.upper() == 'ERROR':
+        log.error(message)
+    elif level.upper() == 'WARNING':
+        log.warning(message)
+    elif level.upper() == 'INFO':
+        log.info(message)
+    elif level.upper() == 'DEBUG':
+        log.debug(message)
+    else:
+        log.warning(f'unknown log_level: {level}')
+
+
+def sleep_random(max_minutes):
+    sleep_time = random.randint(1, 60 * max_minutes)
+    log_message(message=f'{sleep_time} seconds', level='INFO')
+    time.sleep(sleep_time)
+    return
+
+
+# read list of files from dir (eq. (P)IDs or SERIALs) (don't change to uppercase)
+def get_ids_from_dir(directory, refresh_time: int = 0):
+    refresh_time = refresh_time * 86400
+    start_time = int(time.time())
+    ids = []
+    for (dir_path, dir_names, file_names) in os.walk(directory):
+        for entry in file_names:
+            modify_time = int(os.path.getmtime(dir_path + '/' + entry))
+            if (start_time - modify_time) > refresh_time:
+                ids.append(str(entry).replace('_', '/'))
+        # do not read subdirs
+        break
+    # insert cleanup here (filter unwanted names, chars, etc...)
+    return ids
+
+
+# read list of subdirectories from directory (PIDs) (don't anything)
+def get_subdirs_from_dir(base_dir):
+    sub_dirs = []
+    for (dir_path, sub_dirs, filenames) in os.walk(base_dir):
+        break
+    # insert cleanup here (filter unwanted names, chars, etc...)
+    return sub_dirs
+
+
+# read list of IOS/IOSXE Versions from directory (don't change to uppercase)
+def get_version_from_dir(directory):
+    versions = []
+    for (dir_path, dir_names, file_names) in os.walk(directory):
+        for entry in file_names:
+            versions.append(str(entry))
+        # do not read subdirs
+        break
+    # insert cleanup here (filter unwanted names, chars, etc...)
+    return versions
+
+
+# delete (P)IDs or SERIALs files from directory (requests)
+def remove_ids_from_dir(ids, directory):
+    for entry in ids:
+        try:
+            os.remove(directory + entry.replace('/', '_'))
+        except OSError:
+            pass
+
+
+# remove (P)IDs or SERIALs from list of (P)ID or serials
+def remove_ids_from_list(ids, directory):
+    known_ids = []
+    for (dir_path, dir_names, file_names) in os.walk(directory):
+        known_ids.extend(file_names)
+        # do not read subdirs
+        break
+
+    for known_id in known_ids:
+        known_id = known_id.replace('_', '/')
+        for entry in ids:
+            if known_id == entry:
+                ids.remove(entry)
+    return ids
+
+
+# returns al list of ids to refresh,
+# expects a directory with ids to check, the time interval, a list of IDs to add
+# if remove True it will delete the ID files from refresh_dir
+def refresh_ids_from_dir(refresh_dir, refresh_time, ids, remove):
+    refresh_dir = expand_path(refresh_dir)
+    # get seconds from # of days (days * 24 * 60 * 60 --> days * 86400)
+    refresh_time = int(refresh_time) * 86400
+    start_time = int(time.time())
+    refresh_ids = get_ids_from_dir(refresh_dir)
+    if refresh_ids is not []:
+        for entry in refresh_ids:
+            modify_time = int(os.path.getmtime(refresh_dir + entry.replace('/', '_')))
+            if (start_time - modify_time) > refresh_time:
+                ids.append(entry)
+                if remove:
+                    try:
+                        os.remove(refresh_dir + entry.replace('/', '_'))
+                    except OSError:
+                        pass
+    return ids
+
+
+# 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
+def check_dir_and_create(directory):
+    directory = os.path.dirname(directory)
+    if not os.path.exists(directory):
+        try:
+            os.makedirs(directory)
+        except:
+            return False
+    return True
+
+
+# expand homedir and add '/' if necessary and create directory if it not exists
+def expand_path(path):
+    homedir = os.path.expanduser('~')
+
+    if path.startswith('~'):
+        path = homedir + path[1:]
+
+    if not path.endswith('/'):
+        path += '/'
+
+    if not check_dir_and_create(path):
+        return ''
+
+    return path
+
+# remove empty directories
+def remove_empty_sub_dirs(base_dir):
+    subdirs = get_subdirs_from_dir(base_dir)
+    for subdir in subdirs:
+        try:
+            os.rmdir(base_dir + subdir)
+        except OSError as e:
+            log_message(f'can not delete: {base_dir}, Error:{e}')
+            pass
+
+
+# move contents of source_dir to destination_dir
+# only one level deep, lave source_dir
+def move_dir(source_dir, destination_dir, **kwargs):
+    refresh_time = int(kwargs.get('refresh_time', 0)) * 86400
+    starttime = int(time.time())
+
+    sub_dirs = get_subdirs_from_dir(source_dir)
+    for sub_dir in sub_dirs:
+        files = get_ids_from_dir(source_dir + sub_dir)
+        if len(files) > 0:
+            source_path = expand_path(source_dir + sub_dir)
+            destination_path = expand_path(destination_dir + sub_dir)
+            for file in files:
+                source_file = source_path + file
+                destination_file = destination_path + file
+                modify_time = int(os.path.getmtime(source_file))
+                if (starttime - modify_time) > refresh_time:
+                    try:
+                        os.rename(source_file, destination_file)  # rename (move) contents of not_found to request
+                    except OSError as e:
+                        log_message(message=f'error:{e}, source: {source_file}, destionation: {destination_file}',
+                                    level='ERROR')
+
+    remove_empty_sub_dirs(source_dir)
diff --git a/source/bin/ciscoapi/ciscoapi.py b/source/bin/ciscoapi/ciscoapi.py
new file mode 100755
index 0000000..2ec1e74
--- /dev/null
+++ b/source/bin/ciscoapi/ciscoapi.py
@@ -0,0 +1,521 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+
+#  https://developer.cisco.com/docs/support-apis/
+#
+# 2017-03-30: Cisco EoX API Framework
+#             added support for Cisco SN2INFO API (get contract status)
+# 2017-07-09: added support for Cisco Psirt API (IOS and IOSXE)
+# 2017-07-19: added support for Cisco Software Suggestion API
+# 2018-01-25: adding support for Cisco bug api 2.0
+# 2018-09-25: performance improvement "psirt_response.encoding = 'UTF-8'", drops json.loads
+#             from about 4 min to some seconds
+# 2021-07-23: rewritten for python 3.8
+# 2023-06-09: changed for new rest api endpoint (apix.cisco.com)
+#             refactoring get_token and settings
+#             some cleanup
+#
+# supportapis[dash]help[at]cisco[dot]com
+#
+import requests
+import json
+import time
+from os.path import (
+    expanduser,
+)
+from typing import Dict, List
+from cisco_live_cycle_utils import (
+    log_message,
+)
+
+
+class Settings:
+    def __init__(self):
+        conf_file = '~/etc/ciscoapi/ciscoapi.json'
+        conf_file = expanduser(conf_file)
+
+        with open(conf_file) as f:
+            try:
+                self.__settings = json.load(f)
+            except ValueError as e:
+                log_message(f'ciscoapi:settings:JSON load error: {e}', level='WARNING')
+                exit()
+            except FileNotFoundError as e:
+                log_message(f'Config file not found {e}.', level='CRITICAL')
+                exit()
+
+        self.__base_path = '~/var/ciscoapi'
+        self.__auth_proxy_url = 'https://cmk.bech-noc.de/api/cauthproxy.py'
+        self.__proxies = {}
+        self.__wait_after_start = True
+        self.__max_wait_time = 15
+        self.__log_level = 'warning'
+        self.__eox_refresh_known = 31
+        self.__eox_refresh_unknown = 7
+        self.__sn2info_refresh_covered = 31
+        self.__sn2info_refresh_not_covered = 7
+        self.__bug_refresh_found = 2
+        self.__bug_refresh_not_found = 1
+        self.__psirt_refresh_found = 1
+        self.__psirt_refresh_not_found = 1
+        self.__suggestion_refresh_found = 31
+        self.__suggestion_refresh_not_found = 7
+
+        if self.__settings['global'].get('http_proxy'):
+            self.__proxies .update({'http': self.__settings['global'].get('http_proxy')})
+        if self.__settings['global'].get('https_proxy'):
+            self.__proxies .update({'https': self.__settings['global'].get('https_proxy')})
+
+    @property
+    def client_id(self) -> str:
+        return self.__settings['cisco_api']['client_id']
+
+    @property
+    def client_secret(self) -> str:
+        return self.__settings['cisco_api']['client_secret']
+
+    @property
+    def proxies(self) -> Dict[str, str]:
+        return self.__proxies
+
+    @property
+    def use_system_proxies(self) -> bool:
+        return self.__settings['global'].get('use_system_proxies', False)
+
+    @property
+    def use_auth_proxy(self) -> bool:
+        return self.__settings['cisco_api'].get('use_auth_proxy', False)
+
+    @property
+    def client_fqdn(self) -> str:
+        return self.__settings['cisco_api'].get('client_fqdn')
+
+    @property
+    def root_cert(self) -> bool:
+        return self.__settings['cisco_api'].get('root_cert', False)
+
+    @property
+    def auth_proxy_url(self) -> str:
+        return self.__settings['cisco_api'].get('auth_proxy_url')
+
+    @property
+    def base_path(self) -> str:
+        return self.__settings['global'].get('base_path', self.__base_path)
+
+    @property
+    def wait_after_start(self) -> bool:
+        return self.__settings['global'].get('wait_after_start', self.__wait_after_start)
+
+    @property
+    def max_wait_time(self) -> int:
+        return self.__settings['global'].get('max_wait_time', self.__max_wait_time)
+
+    @property
+    def log_level(self) -> str:
+        return self.__settings['global'].get('log_level', self.__log_level)
+
+    @property
+    def eox_refresh_known(self) -> int:
+        return self.__settings['eox'].get('refresh_known', self.__eox_refresh_known)
+
+    @property
+    def eox_refresh_unknown(self) -> int:
+        return self.__settings['eox'].get('refresh_known', self.__eox_refresh_unknown)
+
+    @property
+    def sn2info_refresh_covered(self) -> int:
+        return self.__settings['sn2info'].get('refresh_covered', self.__sn2info_refresh_covered)
+
+    @property
+    def sn2info_refresh_not_covered(self) -> int:
+        return self.__settings['sn2info'].get('refresh_not_covered', self.__sn2info_refresh_not_covered)
+
+    @property
+    def bug_refresh_found(self) -> int:
+        return self.__settings['bug'].get('refresh_found', self.__bug_refresh_found)
+
+    @property
+    def bug_refresh_not_found(self) -> int:
+        return self.__settings['bug'].get('refresh_found', self.__bug_refresh_not_found)
+
+    @property
+    def psirt_refresh_found(self) -> int:
+        return self.__settings['psirt'].get('refresh_found', self.__psirt_refresh_found)
+
+    @property
+    def psirt_refresh_not_found(self) -> int:
+        return self.__settings['psirt'].get('refresh_not_found', self.__psirt_refresh_not_found)
+
+    @property
+    def suggestion_refresh_found(self) -> int:
+        return self.__settings['suggestion'].get('refresh_found', self.__suggestion_refresh_found)
+
+    @property
+    def suggestion_refresh_not_found(self) -> int:
+        return self.__settings['suggestion'].get('refresh_not_found', self.__suggestion_refresh_not_found)
+
+
+class AccessToken:
+    def __init__(
+            self,
+            client_id: str,
+            client_secret: str,
+            proxies: Dict,
+    ):
+        self.__client_id = client_id
+        self.__client_secret = client_secret
+        self.__proxies = proxies
+        self.__use_auth_proxy = None
+        self.__client_fqdn = ''
+        self.__root_cert = True
+        self.__auth_proxy_url = 'https://cmk.bech-noc.de/api/cauthproxy.py'
+        self.__access_token = ''
+        self.__lifetime = 0
+        self.__time = 0
+        self.__auth_headers = {
+            'content-Type': 'application/x-www-form-urlencoded',
+            'accept': 'application/json'
+        }
+        self.__grant_type = 'client_credentials'
+        self.__auth_url = 'https://id.cisco.com/oauth2/default/v1/token'
+        self.__verify = True
+        self.__auth_req_data = {
+            'client_id': self.__client_id,
+            'client_secret': self.__client_secret,
+            'grant_type': self.__grant_type
+        }
+
+    @property
+    def token(self) -> str:
+        if self.__access_token and time.time() < self.__lifetime:
+            return self.__access_token
+        else:
+            self.__time = time.time()
+            response = requests.post(
+                self.__auth_url,
+                headers=self.__auth_headers,
+                data=self.__auth_req_data,
+                proxies=self.__proxies,
+                verify=self.__verify)
+
+        if response.ok:
+            auth_response = json.loads(response.text)
+            self.__lifetime = self.__time + int(auth_response.get("expires_in")) - 60
+            self.__access_token = auth_response.get("access_token")
+            return self.__access_token
+
+
+# generic cisco api request for all get info by serialnumber
+def get_info_by_serials(
+        serials: List[str],
+        access_token: AccessToken,
+        req_url: str,
+        max_serials: int,
+        settings: Settings
+):
+    # locale variablen
+    max_serial_length = 40
+    max_req_per_second = 5
+    wait_time = 5
+    optimisedserials = []
+    serialsstr = ''
+    count = 1
+    info = []
+
+    # split list of Serials in chunks of max 75 serials, each max 40 bytes length
+    for serial in serials:
+        if len(serial) <= max_serial_length:
+            serialsstr += serial + ","
+            count += 1
+        if count == max_serials:
+            optimisedserials.append(serialsstr[:-1])
+            serialsstr = ''
+            count = 1
+    optimisedserials.append(serialsstr[:-1])
+
+    headers = {'accept': 'application/json', 'Authorization': 'Bearer ' + access_token.token}
+
+    count = 0
+    for serials in optimisedserials:
+        # Disable invalid certificate warnings.
+        # requests.packages.urllib3.disable_warnings()
+        response = requests.get(req_url + serials, headers=headers, proxies=settings.proxies)
+        count += 1
+        # only 5 request per second are allowed
+        if count == max_req_per_second:
+            time.sleep(wait_time)
+            count = 0
+        if response.ok:
+            response.encoding = 'UTF-8'
+            info.append(json.loads(response.text))
+
+    return info
+
+
+def get_eox_by_pid(pids: List[str], access_token: AccessToken, settings: Settings):
+    # local variables
+    max_pid_length = 240
+    max_pids = 20
+    max_req_per_second = 5
+    wait_time = 5
+    optimisedpids = []
+    pidstr = ''
+    count = 1
+    eoxr = []
+
+    # split list of PIDs in chunks of max 240 bytes length
+    for pid in pids:
+        if (len(pidstr) + len(pid)) < max_pid_length:
+            pidstr += pid + ","
+            count += 1
+        if (count == max_pids) or ((len(pidstr) + len(pid)) >= max_pid_length):
+            optimisedpids.append(pidstr[:-1])
+            pidstr = ''
+            count = 1
+    optimisedpids.append(pidstr[:-1])
+    headers = {'accept': 'application/json', 'Authorization': f'Bearer {access_token.token}'}
+    req_url = 'https://apix.cisco.com/supporttools/eox/rest/5/EOXByProductID/1/'
+
+    count = 0
+    for productids in optimisedpids:
+        # Disable invalid certificate warnings.
+        # requests.packages.urllib3.disable_warnings()
+        eoxresponse = requests.get(req_url + productids, headers=headers, proxies=settings.proxies)
+        count += 1
+        # only 5 request per second are allowed
+        if count == max_req_per_second:
+            time.sleep(wait_time)
+            count = 0
+        if eoxresponse.ok:
+            eoxr.append(json.loads(eoxresponse.text))
+    return eoxr
+
+
+def get_eox_by_serials(serials: List[str], access_token: AccessToken, settings: Settings):
+    max_serials = 20
+    req_url = 'https://apix.cisco.com/supporttools/eox/rest/5/EOXBySerialNumber/1/'
+    info = get_info_by_serials(serials, access_token, req_url, max_serials, settings)
+    return info
+
+
+def get_coverage_summary_by_serials(serials: List[str], access_token: AccessToken, settings: Settings):
+    max_serials = 75
+    req_url = 'https://apix.cisco.com/sn2info/v2/coverage/summary/serial_numbers/'
+    info = get_info_by_serials(serials, access_token, req_url, max_serials, settings)
+    return info
+
+
+def get_psirt_by_ios_version(psirtios: List[str], access_token: AccessToken, settings: Settings):
+    info = []
+
+    headers = {'accept': 'application/json', 'Authorization': 'Bearer ' + access_token.token}
+    req_url = 'https://apix.cisco.com/security/advisories/ios?version='
+
+    # requests.packages.urllib3.disable_warnings()
+    if list(psirtios) is not []:
+        for ios_version in psirtios:
+            log_message('request ios_version: %s, time: %s' % (ios_version, time.asctime(time.localtime(time.time()))))
+            psirt_response = requests.get(req_url + ios_version, headers=headers, proxies=settings.proxies)
+            if psirt_response.ok:
+                log_message(
+                    f'ok. ios_version: {ios_version}, '
+                    f'time: {time.asctime(time.localtime(time.time()))}, '
+                    f'len: {len(str(psirt_response))}'
+                )
+                # makes json.loads() mutch more faster (from 4 min. down to 1 sec for about 2MB)
+                psirt_response.encoding = 'UTF-8'
+                response = (json.loads(psirt_response.text))
+                log_message(
+                    f'response loaded: ios_version: {ios_version}, '
+                    f'time: {time.asctime(time.localtime(time.time()))}, '
+                    f'len: {len(str(response))}'
+                )
+                info.append({'version': ios_version, 'advisories': response.get('advisories', 'notfound')})
+                log_message('ciscoapi:psirt-ios-found: %s' % info)
+            else:
+                log_message(
+                    f'notfound. ios_version: {ios_version}, '
+                    f'time: {time.asctime(time.localtime(time.time()))}, '
+                    f'len: {len(str(psirt_response))}'
+                )
+                info.append({'version': ios_version, 'advisories': 'notfound'})
+                log_message('ciscoapi:psirt-ios-notfound: %s' % info)
+    return info
+
+
+def get_psirt_by_iosxe_version(psirtios: List[str], access_token: AccessToken, settings: Settings):
+    info = []
+
+    headers = {'accept': 'application/json', 'Authorization': 'Bearer ' + access_token.token}
+    req_url = 'https://apix.cisco.com/security/advisories/iosxe?version='
+
+    # requests.packages.urllib3.disable_warnings()
+    if list(psirtios) is not []:
+        for ios_version in psirtios:
+            psirt_response = requests.get(req_url + ios_version, headers=headers, proxies=settings.proxies)
+            if psirt_response.ok:
+                psirt_response.encoding = 'UTF-8'
+                response = (json.loads(psirt_response.text))
+                info.append({'version': ios_version, 'advisories': response.get('advisories', 'notfound')})
+                log_message(f'ciscoapi:psirt-iosxe-found: {info}')
+            else:
+                info.append({'version': ios_version, 'advisories': 'notfound'})
+                log_message(f'ciscoapi:psirt-iosxe-notfound: {info}')
+    return info
+
+
+def get_psirt_by_product_family(families: List[str], access_token: AccessToken, settings: Settings):
+    info = []
+
+    headers = {'accept': 'application/json', 'Authorization': 'Bearer ' + access_token.token}
+    req_url = 'https://apix.cisco.com/security/advisories/cvrf/product?product='
+
+    # requests.packages.urllib3.disable_warnings()
+    if list(families) is not []:
+        for family in families:
+            psirt_response = requests.get(req_url + family, headers=headers, proxies=settings.proxies)
+            if psirt_response.ok:
+                psirt_response.encoding = 'UTF-8'
+                response = (json.loads(psirt_response.text))
+                info.append({'family': family, 'advisories': response.get('advisories', 'notfound')})
+                log_message('ciscoapi:psirt-family-found: %s' % info)
+            else:
+                info.append({'family': family, 'advisories': 'notfound'})
+                log_message('ciscoapi:psirt-family-notfound: %s' % info)
+    return info
+
+
+# get_clean_sn_for_bug_api('ASA5510', '9.1(7)15,8.4(7)30,9.1(6)1')
+# return {'9.1(7)15': '9.1(7.15)', '9.1(6)1': '9.1(6.1)', '8.4(7)30': '8.4(7.30)'}
+def get_clean_sn_for_bug_api(pid, software_releases):
+    if software_releases == '' or pid == '':
+        return {}
+    software_releases = software_releases.split(',')
+    clean_sns = {}
+
+    if pid.startswith('ASA'):
+        # change ASA version from 9.1(2)10 to 9.1(2.10)
+        for software_release in software_releases:
+            clean_sn = software_release
+            if clean_sn[-1] != ')':
+                clean_sn = clean_sn.split(')')
+                if len(clean_sn) == 2:
+                    clean_sn = '%s.%s)' % (clean_sn[0], clean_sn[1])
+            clean_sns.update({software_release: clean_sn})
+
+    elif pid.startswith('AIR'):
+        # change WLC version from 8.5.120.0 to 8.5(120.0)
+        for software_release in software_releases:
+            clean_sn = software_release
+            if clean_sn[-1] != ')':
+                if len(clean_sn.split('.')) == 4:
+                    clean_sn = clean_sn.split('.')
+                    clean_sn = '%s.%s(%s.%s)' % (clean_sn[0], clean_sn[1], clean_sn[2], clean_sn[3])
+            clean_sns.update({software_release: clean_sn})
+
+    else:
+        for software_release in software_releases:
+            clean_sn = software_release
+            if clean_sn.startswith('16.0'):
+                # remove leading zeros 16.09.01 to 16.9.1
+                clean_sn = clean_sn.split('.')
+                for x in range(0, len(clean_sn)):
+                    clean_sn[x] = clean_sn[x].lstrip('0')
+                    if clean_sn[x] == '':
+                        clean_sn = '0'
+                clean_sn = '.'.join(clean_sn)
+                # remove trailing A-Za-z
+                while clean_sn[-1].upper() in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
+                    clean_sn = clean_sn[:-1]
+            elif clean_sn.startswith('03.0'):
+                # convert version from 03.03.04SE to 3.3(4)SE
+                clean_sn = clean_sn.split('.')
+                for x in range(0, len(clean_sn)):
+                    clean_sn[x] = clean_sn[x].lstrip('0')
+                    if clean_sn[x] == '':
+                        clean_sn = '0'
+                digits = ''
+                for x in clean_sn[2]:
+                    if x.isdigit():
+                        digits += x
+                clean_sn[2] = clean_sn[2].replace(digits, '')
+                clean_sn = '%s.%s(%s)%s' % (clean_sn[0], clean_sn[1], digits, clean_sn[2])
+            clean_sns.update({software_release: clean_sn})
+
+    return clean_sns
+
+
+def get_bug_by_pid_and_release(pid, release, access_token: AccessToken, reqoptions, settings: Settings):
+    info = []
+
+    headers = {'accept': 'application/json', 'Authorization': 'Bearer ' + access_token.token}
+    req_url = 'https://apix.cisco.com/bug/v2.0/bugs/products/product_id/'
+
+    if release != '':
+        software_releases = get_clean_sn_for_bug_api(pid, release)
+        clean_sn = ','.join(software_releases.values())
+        missing = {}
+        bug_response = requests.get(
+            url=req_url + f'{pid}/software_releases/{clean_sn}{reqoptions}',
+            headers=headers,
+            proxies=settings.proxies
+        )
+        if bug_response.ok:
+            bug_response.encoding = 'UTF-8'
+            response = (json.loads(bug_response.text))
+            bug_list = response.get('bugs')
+            pagination_record = response.get('pagination_response_record')
+            last_page = int(pagination_record.get('last_index'))
+            total_records = int(pagination_record.get('total_records'))
+            log_message(message=f'PID: {pid}, Version: {clean_sn}, Total records: {total_records}, Pages: {last_page}',
+                        level='INFO')
+            if last_page > 1:
+                if reqoptions != '':
+                    reqoptions = reqoptions + '&page_index='
+                else:
+                    reqoptions = '?page_index='
+                for page in range(2, last_page + 1):
+                    # time.sleep(2)
+                    page_options = reqoptions + '%s' % page
+                    bug_response = requests.get(req_url + f'{pid}/software_releases/{clean_sn}{page_options}',
+                                                headers=headers, proxies=settings.proxies)
+                    if bug_response.ok:
+                        response = (json.loads(bug_response.text))
+                        bug_list += response.get('bugs')
+                    else:
+                        bug_response.encoding = 'UTF-8'
+                        status_code = bug_response.status_code
+                        reason = bug_response.reason
+                        url = bug_response.url
+                        text = bug_response.text
+                        log_message(message=f'ciscoapi error: {status_code}, {reason}, Page: {page}, LastPage: '
+                                            f'{last_page}, URL: \'{url}\'. Text: \'{text}\'',
+                                    level='WARNING')
+                        missing.update({page: {'status_code': status_code,
+                                               'reason': reason,
+                                               'url': url,
+                                               'text': text}})
+            info.append({'pid': pid,
+                         'software_releases': software_releases,
+                         'bugs': bug_list,
+                         'total_records': total_records,
+                         'missing': missing})
+            log_message('ciscoapi:bug-found: %s' % info)
+        else:
+            bug_response.encoding = 'UTF-8'
+            status_code = bug_response.status_code
+            reason = bug_response.reason
+            url = bug_response.url
+            text = bug_response.text
+            page = 'ALL'
+            log_message(f'ciscoapi error: {status_code}, {reason}, URL: \'{url}\'. Text: \'{text}\'', level='WARNING')
+            missing.update({page: {'status_code': status_code,
+                                   'reason': reason,
+                                   'url': url,
+                                   'text': text}})
+            info.append({'pid': pid,
+                         'software_releases': software_releases,
+                         'status_code': status_code,
+                         'reason': reason,
+                         'missing': missing})
+    return info
diff --git a/gui/views/inv_cisco_livecycle.py b/source/gui/views/inv_cisco_livecycle.py
similarity index 100%
rename from gui/views/inv_cisco_livecycle.py
rename to source/gui/views/inv_cisco_livecycle.py
diff --git a/gui/wato/inv_cisco_bug.py b/source/gui/wato/inv_cisco_bug.py
similarity index 100%
rename from gui/wato/inv_cisco_bug.py
rename to source/gui/wato/inv_cisco_bug.py
diff --git a/gui/wato/inv_cisco_contract.py b/source/gui/wato/inv_cisco_contract.py
similarity index 100%
rename from gui/wato/inv_cisco_contract.py
rename to source/gui/wato/inv_cisco_contract.py
diff --git a/gui/wato/inv_cisco_eox.py b/source/gui/wato/inv_cisco_eox.py
similarity index 100%
rename from gui/wato/inv_cisco_eox.py
rename to source/gui/wato/inv_cisco_eox.py
diff --git a/gui/wato/inv_cisco_psirt.py b/source/gui/wato/inv_cisco_psirt.py
similarity index 100%
rename from gui/wato/inv_cisco_psirt.py
rename to source/gui/wato/inv_cisco_psirt.py
diff --git a/packages/inv_cisco_support b/source/packages/inv_cisco_support
similarity index 98%
rename from packages/inv_cisco_support
rename to source/packages/inv_cisco_support
index 34bca19..71a5323 100644
--- a/packages/inv_cisco_support
+++ b/source/packages/inv_cisco_support
@@ -40,5 +40,5 @@
           'suggested software',
  'version': '0.3.0-20231025',
  'version.min_required': '2.2.0b1',
- 'version.packaged': '2.2.0p11',
+ 'version.packaged': '2.2.0p24',
  'version.usable_until': '2.3.0b1'}
diff --git a/web/htdocs/css/inv_cisco_support.css b/source/web/htdocs/css/inv_cisco_support.css
similarity index 100%
rename from web/htdocs/css/inv_cisco_support.css
rename to source/web/htdocs/css/inv_cisco_support.css
-- 
GitLab