Skip to content
Snippets Groups Projects
Commit 422f6b3f authored by geant-release-service's avatar geant-release-service
Browse files

Finished release 0.20.

parents fe5b0c18 475d7188
No related branches found
No related tags found
No related merge requests found
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [0.20] - 2025-06-05
- Fix exception propagation and logging/exiting properly when exception occurs in the daemon thread (actually include the changes this time)
## [0.19] - 2025-06-04
- Fix exception propagation and logging/exiting properly when exception occurs in the daemon thread
## [0.18] - 2025-05-30 ## [0.18] - 2025-05-30
- Add 15s timeout to inventory-provider GET request, instead of default no timeout - Add 15s timeout to inventory-provider GET request, instead of default no timeout
......
...@@ -4,9 +4,10 @@ import logging ...@@ -4,9 +4,10 @@ import logging
import sys import sys
import threading import threading
import traceback import traceback
from multiprocessing import Queue
from datetime import datetime from datetime import datetime
from logging import LogRecord from logging import LogRecord
from typing import Any, Collection, Dict, Iterable, List from typing import Any, Collection, Dict, Iterable, List, Optional
import click import click
import jsonschema import jsonschema
...@@ -187,40 +188,48 @@ ALL_ = object() ...@@ -187,40 +188,48 @@ ALL_ = object()
def main( def main(
exception_queue: Optional[Queue],
processor: RouterProcessor, processor: RouterProcessor,
interfaces=ALL_, interfaces=ALL_,
output: OutputMethod = OutputMethod.INFLUX, output: OutputMethod = OutputMethod.INFLUX,
): ):
logger.info( try:
f"Processing {processor.name.capitalize()} router {processor.router_fqdn}" logger.info(
) f"Processing {processor.name.capitalize()} router {processor.router_fqdn}"
)
timestamp = datetime.now() timestamp = datetime.now()
for point_group in processor.supported_point_groups: for point_group in processor.supported_point_groups:
logger.info(f"Processing {str(point_group).upper()} points...") logger.info(f"Processing {str(point_group).upper()} points...")
inventory = processor.config.get("inventory") inventory = processor.config.get("inventory")
check_interfaces = None check_interfaces = None
if inventory is not None: if inventory is not None:
check_interfaces = load_interfaces( check_interfaces = load_interfaces(
router_fqdn=processor.router_fqdn, router_fqdn=processor.router_fqdn,
interfaces=interfaces, interfaces=interfaces,
point_group=point_group,
config=processor.config,
)
if not check_interfaces:
logger.info(f"No {str(point_group).upper()} interfaces found")
continue
process_router(
processor=processor,
point_group=point_group, point_group=point_group,
config=processor.config, interfaces=check_interfaces,
timestamp=timestamp,
output=output,
) )
if not check_interfaces: except Exception:
logger.info(f"No {str(point_group).upper()} interfaces found") if not exception_queue:
continue raise # no queue means we don't run in a thread, so we can just raise the exception
exc_info = sys.exc_info()
process_router( formatted = ''.join(traceback.format_exception(*exc_info))
processor=processor, exception_queue.put(formatted)
point_group=point_group,
interfaces=check_interfaces,
timestamp=timestamp,
output=output,
)
def validate_config(_unused_ctx, _unused_param, file): def validate_config(_unused_ctx, _unused_param, file):
...@@ -296,14 +305,16 @@ def cli( ...@@ -296,14 +305,16 @@ def cli(
error_counter = setup_logging(debug=verbose) error_counter = setup_logging(debug=verbose)
try: exception_queue = Queue()
thread = threading.Thread(
target=main, thread = threading.Thread(
args=(processor, interfaces if interfaces else ALL_, OutputMethod.from_string(output.lower())), target=main,
) args=(exception_queue, processor, interfaces if interfaces else ALL_, OutputMethod.from_string(output.lower())),
thread.daemon = True )
thread.start() thread.daemon = True
thread.join(timeout=120) thread.start()
thread.join(timeout=120)
if thread.is_alive() or not exception_queue.empty():
if thread.is_alive(): if thread.is_alive():
logger.error("Thread timed out") logger.error("Thread timed out")
frames = sys._current_frames() frames = sys._current_frames()
...@@ -313,13 +324,11 @@ def cli( ...@@ -313,13 +324,11 @@ def cli(
for line in traceback.format_stack(frame): for line in traceback.format_stack(frame):
logger.error(line.strip()) logger.error(line.strip())
logger.error("-- Thread stack trace end --") logger.error("-- Thread stack trace end --")
raise click.exceptions.Exit(2) else:
logger.error(f"Error while processing {processor.name.capitalize()} router {router_fqdn}:")
exception = exception_queue.get()
logger.error(exception)
except Exception:
logger.exception(
f"Error while processing {processor.name.capitalize()} router {router_fqdn}"
)
# Exit code 2 indicates CRITICAL in Sensu
raise click.exceptions.Exit(2) raise click.exceptions.Exit(2)
if error_counter.count: if error_counter.count:
......
...@@ -2,7 +2,7 @@ from setuptools import setup, find_packages ...@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup( setup(
name='brian-polling-manager', name='brian-polling-manager',
version="0.19", version="0.20",
author='GEANT', author='GEANT',
author_email='swd@geant.org', author_email='swd@geant.org',
description='service for managing BRIAN polling checks', description='service for managing BRIAN polling checks',
......
...@@ -157,6 +157,7 @@ def test_main_for_all_juniper_routers( ...@@ -157,6 +157,7 @@ def test_main_for_all_juniper_routers(
write_points.side_effect = validate write_points.side_effect = validate
cli.main( cli.main(
None,
processor=JuniperRouterProcessor(juniper_router_fqdn, config), processor=JuniperRouterProcessor(juniper_router_fqdn, config),
interfaces=juniper_inventory[juniper_router_fqdn], interfaces=juniper_inventory[juniper_router_fqdn],
) )
...@@ -187,6 +188,7 @@ def test_main_with_some_interfaces( ...@@ -187,6 +188,7 @@ def test_main_with_some_interfaces(
"error-counters": {}, "error-counters": {},
} }
cli.main( cli.main(
None,
processor=JuniperRouterProcessor("mx1.ams.nl.geant.net", config), processor=JuniperRouterProcessor("mx1.ams.nl.geant.net", config),
interfaces=["ifc1"], interfaces=["ifc1"],
) )
...@@ -204,6 +206,7 @@ def test_main_with_all_interfaces_and_inprov_hosts( ...@@ -204,6 +206,7 @@ def test_main_with_all_interfaces_and_inprov_hosts(
"error-counters": {}, "error-counters": {},
} }
cli.main( cli.main(
None,
processor=JuniperRouterProcessor("mx1.ams.nl.geant.net", config), processor=JuniperRouterProcessor("mx1.ams.nl.geant.net", config),
) )
assert process_router.call_args[1]["interfaces"].keys() == {"ifc1", "ifc2"} assert process_router.call_args[1]["interfaces"].keys() == {"ifc1", "ifc2"}
...@@ -219,6 +222,7 @@ def test_main_with_all_interfaces_no_inprov_hosts( ...@@ -219,6 +222,7 @@ def test_main_with_all_interfaces_no_inprov_hosts(
"error-counters": {"influx": None}, "error-counters": {"influx": None},
} }
cli.main( cli.main(
None,
processor=JuniperRouterProcessor("mx1.ams.nl.geant.net", config), processor=JuniperRouterProcessor("mx1.ams.nl.geant.net", config),
) )
assert process_router.call_args[1]["interfaces"] is None assert process_router.call_args[1]["interfaces"] is None
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment