sunet-fleetlock: handle connection errors

In order to handle upgrades of the fleetlock server when running only
one server we need to handle connection errors like connection refused
or timed out errors gracefully.

Because there are several different ways the connection can fail and it
is hard to keep track of them all, just catch everything. We then also
need special handling of our own timeout execption so we are not
accidentally stuck retrying forever.

Also fix so we actually use the request_timeout arg for individual HTTP
requests instead of the global timeout.

While here run isort to keep imports tidy.
This commit is contained in:
Patrik Lundin 2024-06-17 11:54:28 +02:00
parent 646c40daf1
commit 4b8b8887f6
Signed by: patlu
GPG key ID: A0A812BA2249F294

View file

@ -24,20 +24,21 @@
# When modifying this code please make sure it is passed through the following # When modifying this code please make sure it is passed through the following
# tools: # tools:
# === # ===
# isort
# black # black
# pylint # pylint
# mypy --strict # mypy --strict
# === # ===
import platform
import sys
import signal
import time
import argparse import argparse
import configparser import configparser
import os.path import os.path
from typing import Optional, Union import platform
import signal
import sys
import time
from types import FrameType from types import FrameType
from typing import Optional, Union
import requests import requests
@ -80,19 +81,29 @@ def do_fleetlock_request(
request_id_key = "request-id" request_id_key = "request-id"
request_id = None request_id = None
retry_sleep_delay = 1
# Loop forever: we depend on the SIGALRM timout to raise an error if it # Loop forever: we depend on the SIGALRM timout to raise an error if it
# takes too long # takes too long
while True: while True:
if args.verbose: if args.verbose:
print(f"{operation} POST at url {url}") print(f"{operation} POST at url {url}")
try:
resp = requests.post( resp = requests.post(
url, url,
headers=fleetlock_headers, headers=fleetlock_headers,
json=fleetlock_data, json=fleetlock_data,
timeout=args.timeout, timeout=args.request_timeout,
auth=("", config[args.lock_group]["password"]), auth=("", config[args.lock_group]["password"]),
) )
except Exception as e: # pylint: disable=broad-exception-caught
if isinstance(e, TimeoutException):
# This means our global timer is up, no more time to retry
raise e
print(f"POST request failed: {e}")
time.sleep(retry_sleep_delay)
continue
if request_id_key in resp.headers: if request_id_key in resp.headers:
request_id = resp.headers[request_id_key] request_id = resp.headers[request_id_key]
@ -126,7 +137,7 @@ def do_fleetlock_request(
+ f"({request_id_key}: {request_id})" + f"({request_id_key}: {request_id})"
) )
time.sleep(1) time.sleep(retry_sleep_delay)
def read_config(args: argparse.Namespace) -> Union[configparser.ConfigParser, None]: def read_config(args: argparse.Namespace) -> Union[configparser.ConfigParser, None]: