All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Add CONTRIBUTING
- Add GitHub Actions workflow to automatically build and deploy API documentation to GitHub Pages
- Add pre-commit hooks
- disk.py: add
get_owner() - nextcloud.py: new library
- txt.py: add
exception2text() - winrm.py: add
WINRM_CONFIGURATION_NAMEoption torun_ps() - winrm.py: execute ps in
run_ps()directly without Invoke-Expression wrapping
- Bump minimum Python version from 3.6 to 3.9
- base.py:
get_perfdata()now sanitizes labels by stripping single quotes and replacing=with_ - base.py: deduplicate
get_state()operator logic usingoperatormodule - base.py: deduplicate
sum_dict()by delegating tosum_lod() - base.py:
get_table(): document why pure ASCII delimiters are used instead of Unicode box-drawing characters - base.py: improve
get_table()performance for large tables - base.py: move
parse_range()and state name mapping to module level - base.py: remove unused
collectionsimport - base.py: strip trailing semicolons in
get_perfdata()output - db_sqlite.py: reduce unnecessary dictionary object creation
- human.py: deduplicate
bits2human()/bps2human()/bytes2human()via shared_to_human()helper - human.py: deduplicate
humanrange2bytes()/humanrange2seconds()via shared_convert_range()helper - human.py: pre-compute mappings as module constants
- powershell.py:
run_ps()now always returns a dict - Remove pre-built documentation from the repository (now auto-deployed via GitHub Actions)
- txt.py: improve
filter_mltext()performance (avoid O(n²) string concatenation) - txt.py: improve readability of
extract_str()fallback logic - txt.py: remove unused Python 2 type aliases and outdated comments
- txt.py: simplify
to_text()andto_bytes()for Python 3 only (remove dead Python 2 codepaths) - winrm.py: make
run_cmd()andrun_ps()JEA-aware - winrm.py: make
run_cmd()andrun_ps()Kerberos-aware
- base.py:
cu()now also escapes HTML characters in the error message, not just in the traceback - base.py:
cu()now detects active exceptions viasys.exc_info()instead of string-matching the traceback - base.py:
get_state()no longer callssys.exit()on malformed range specs, returns UNKNOWN instead - base.py:
oao()now escapes HTML characters in the output message to prevent injection in web UIs - base.py: fix
get_table()using wrong separator for the second data row when called without a header - base.py: fix invalid
-10range example in_parse_range()docstring (correct syntax is-10:0) - human.py: fix incorrect
seconds2human()docstring example for sub-second values - powershell.py: fix outdated shebang line
- shell.py:
shell_exec()now applies timeout to theshell=Truepath (was previously ignored) - txt.py:
sanitize_sensitive_data()now also redacts JSON-style fields and HTTP Authorization headers - txt.py: fix
exception2text()missingtracebackimport (fallback path was dead code) - txt.py: fix
pluralize()not stripping whitespace from comma-separated suffix parts - txt.py: fix
sanitize_sensitive_data()replacing the key name instead of the secret value - winrm.py: pass parameters correctly in
run_cmd()when using pypsrp
v2.4.0 - 2025-09-17
- rocket.py: add
get_groups_history(),get_rooms_info(),send2webhook() - time.py: add
get_weekday()
- args.py: add
--stratumparameter - args.py: add
--verboseparameter - dmidecode.py: collapse near-duplicate data in an admin-friendly way
- base.py:
get_table()no longer modifies the inputdata - redfish.py: check sensor state against user thresholds first
v2.3.0 - 2025-06-20
- endoflifedate.py: add Icinga
- shell.py: add optional parameter
lc_all='C'toshell_exec()
- distro.py: incorrect
os_familyfor Devuan inget_distribution_facts()(#87)
v2.2.1 - 2025-05-30
- net.py: use
ssl.PROTOCOL_TLS_CLIENTas best practice infetch_ssl()
v2.2.0 - 2025-05-30
- time.py: add
get_timezone() - tools/update-endoflifedate: add Valkey
- net.py: force
fetch_ssl()to use TLS 1.2+ - txt.py: enhance sanitize regex
v2.1.1.15 - 2025-05-07
- net.py: add
fetch_socket()andfetch_ssl(), improvefetch()
v2.1.1.7 - 2025-04-21
- distro.py: move
get_os_info()from version.py to distro.py - human.py: simplify
bits2human()parameters (no more %-syntax) - Improve code style across all libraries
v2.1.1.5 - 2025-04-19
- txt.py: add
sanitize_sensitive_data()
- base.py, url.py: use
txt.sanitize_sensitive_data() - disk.py:
get_real_disks()now ignores loop devices - docs: improve and convert docstrings to Markdown, create
docsfolder usingpdoc - shell.py: remove optional output from Windows
chcpcommand
- shell.py: fix special character decoding in Windows output by switching to codepage 65001
v2.1.0.7 - 2025-04-08
- disk.py: fix static path to
udevadm(#85)
v2.1.0.4 - 2025-03-29
- uptimerobot.py: add handling of PSPs, restructure code
v2.1.0.0 - 2025-03-23
- uptimerobot.py: new library for the UptimeRobot API
v2.0.0.7 - 2025-03-10
- tools/update-endoflifedate: add OpenVPN
- txt.py: fix
extract_str()
v2.0.0.0 - 2025-02-15
- Rename test.py to lftest.py due to
nuitkacompilation error on Windows. - Switch from calendar versioning to semantic versioning due to conventional commits and Windows MSI requirements.
- keycloak.py: new library for Keycloak API interactions
- db_sqlite.py:
create_index(),cut(),delete(),insert(),replace(), andselect()now delete the underlying SQLite db file by default onOperationalError(e.g., when new SQL references columns missing in an older db file). Disable withdelete_db_on_operational_error=False. - librenms.py:
get_state()returnsSTATE_OKinstead ofSTATE_UNKNOWN - url.py: improve error messages and comments
- disk.py: fix
ValueErrorif value contains=
2024060401 - 2024-06-04
Minor improvements, barely any changes.
2024052901 - 2024-05-29
- librenms.py:
get_state()now expects numeric status codes
- args.py: add
help() - base.py: add
str2bool() - disk.py: add
get_real_disks(),udevadm() - human.py: add
human2seconds() - txt.py: add
get_dm_name(),match_regex()
- base.py:
oao()replaces|character in output with!(reserved for performance data separator) - db_sqlite.py: increase connect timeout to 5 seconds in
connect(), returnFalseon failure inclose() - grassfish.py: add
insecure=False, no_proxy=False, timeout=8tofetch_json() - huawei.py: remove hardcoded
insecureparameter inget_creds()andget_data() - icinga.py: remove hardcoded
insecureparameter; addinsecure=False, no_proxy=False, timeout=3to all functions - infomaniak.py: add
insecure=False, no_proxy=False, timeout=8to all functions - jitsi.py: remove hardcoded
insecureand evaluateno_proxyinget_data() - librenms.py: improve
get_data()parameter handling - net.py: add
insecure=False, no_proxy=False, timeout=3toget_public_ip() - nodebb.py: evaluate
no_proxyinget_data() - rocket.py: add
insecure=False, no_proxy=False, timeout=3to all functions - veeam.py: remove hardcoded
insecureand evaluateno_proxyinget_token() - version.py: add
insecure=False, no_proxy=False, timeout=8tocheck_eol() - wildfly.py: evaluate
insecureandno_proxyinget_data()
- base.py:
lookup_lod()never uses the default parameter (#82) - db_mysql.py: fix
select()and providing data - feed.py: incompatible with Azure status RSS (#756)
2023112901 - 2023-11-29
- endoflifedate.py: new auto-built library for end-of-life date tracking
- Published on PyPI, installable via
pip install linuxfabrik-lib - qts.py: new library for the QNAP QTS API
- tools/update-endoflifedate: tool to update endoflifedate.py
- base.py:
cu()appends an optional message, making it a true error message function - base.py:
oao()prints/suffixes ' (always ok)' ifalways_ok=True - shell.py:
shell_exec()merges OS environment variables with those set by theenvparameter - version.py:
check_eol()also fetches and caches info from https://endoflife.date/api
2023051201 - 2023-05-12
- db_mysql.py: change from username/password to option file authentication in
connect() - Remove all Python 2 based plugins and libraries, and remove the "3" suffix from all Python 3 based libraries (#589)
- args.py: add
number_unit_methodtype (used indisk-usagemonitoring plugin) - disk.py: add
read_env() - version.py: new library
- base.py: improve
str2state()
- smb.py:
TypeError: objectSMBDirEntryhas no attributefrom_filename
2023030801 - 2023-03-08
- db_mysql3: change from username/password to option file authentication in
connect() - net3: rename
get_ip_public()toget_public_ip() - net3: rename
ip_to_cdir()tonetmask_to_cdir()
- dmidecode3.py: new library
- grassfish3.py: new library
- base3.py: make
get_worst()more robust - human3.py:
human2bytes()now handles values like "3.0M" - infomaniak3.py: apply new API version
- shell3.py:
shell_exec()also handles timeouts - wildfly3.py: update library
2022072001 - 2022-07-20
- distro3.py: new library
- cache3.py: use more unique default names for SQLite databases
- db_mysql3.py: enhance for new mysql checks
- db_mysql3.py: switch from
mysql.connectortoPyMySQL(#570) - db_sqlite3.py: use more unique default names for SQLite databases
- disk3.py: add
file_exists()function - Revert Python 3.6+ f-strings to
.format()for broader compatibility
2022022801 - 2022-02-28
- human3.py: new library for converting raw numbers and times to human-readable representations
- shell3.py: new library for shell communication
- time3.py: new library for date/time functions
- txt3.py: new library for text handling, encoding, and decoding
- redfish.py: add
get_systems*()functions for Systems collection - winrm.py: add function to run shell commands (#41)
- powershell.py: add PowerShell support (#40)
- base3: move
filter_str()to db_sqlite3.py (#52) - base3: move
get_owner()to nextcloud-version3 (#53) - base3: move
sha1sum()to db_sqlite3.py (#50) - base3: move
x2humanandhuman2xfunctions to new human.py library (#49) - base3: move date/time functions to new time3.py library (#55)
- base3: move shell functions to new shell3.py library (#56)
- base3: move text functions to new txt3.py library (#51)
- Lint all libraries (#57)
- Standardize try-except import statements (#60)
- txt3: handle all encoding and decoding (#59)
- url3.py: extend
fetch_json()to makefetch_json_ext()obsolete - veeam: use new
fetch_json()instead offetch_json_ext()(#42)
- base3: remove
yesterday()function (#54)
- base: fix
hashlib.md5()on FIPS-compliant systems (#30) - base: fix tuple item assignment error (#43)
- librenms-alerts2:
--lengthycauses error (#61) - nginx-status:
TypeError: a bytes-like object is required, not 'str' (#47) - url3.py:
AttributeError: 'str' object has no attribute 'to_bytes' (#62) - url3:
TypeError: a bytes-like object is required, not str (#44) - Various fixes after linting
- veeam.py:
ValueError: need more than 2 values to unpack (#45) - veeam3.py, huawei3.py:
getheader()should beget()in Python 3 (#46)
2021101401 - 2021-10-14
- base: add
utc_offset()function (#35) - db_sqlite: add REGEXP function (#36)
- jitsi.py: new library
- nodebb.py: new library
- test.py: new library for unit testing
- veeam.py: new library
- base2: improve Unicode, UTF-8, and ASCII handling
- base:
get_state()can now evaluate against a range (#34) - base:
version2float()now strips everything except numbers and decimal points (#26) - base: improve line drawing in
get_table()(#7) - base: make
version()more robust (#28) - cache: make filename for cache configurable (#21)
- db_sqlite: support
LIKEstatements using a regexp - get_table(): use ASCII characters only for broadest terminal compatibility (#33)
- url:
fetch()andfetch_json()can now also return HTTP status code and response headers (#32) - url: identify as Linuxfabrik Monitoring Plugin (#24)
- base2:
AttributeError: 'exceptions.ValueError' object has no attribute 'encode' (#37) - base2:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 (#38) - base:
get_table()does not handle length of UTF-8 correctly (#8) - cache3:
NameError: name 'base' is not defined (#29) - db_sqlite: 8-bit bytestrings error with text_factory (#20)
- disk: problems with
read_csv()(#25) - librenms3.py: fix error (#27)
- net:
fetch()port and timeout must be integers (#22) - net: socket
recv()timeout (#23)
2020052801 - 2020-05-28
- db_mysql.py: new library
- feedparser.py: new library
- icinga.py: new library
- base.py: add
shell_exec() - net.py: improvements
- url.py: improvements
2020041501 - 2020-04-15
- args.py: new library
- base.py: new library
- cache.py: new library
- db_sqlite.py: new library
- disk.py: new library
- net.py: new library
- rocket.py: new library
- url.py: new library
2020022801 - 2020-02-28
Initial release.