anta/anta/settings.py
Daniel Baumann 3254dea030
Merging upstream version 1.4.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-05-15 09:34:30 +02:00

86 lines
3.2 KiB
Python

# Copyright (c) 2023-2025 Arista Networks, Inc.
# Use of this source code is governed by the Apache License 2.0
# that can be found in the LICENSE file.
"""Settings for ANTA."""
from __future__ import annotations
import logging
import os
import sys
from typing import Any
from pydantic import Field, PositiveInt
from pydantic_settings import BaseSettings, SettingsConfigDict
from anta.logger import exc_to_str
logger = logging.getLogger(__name__)
DEFAULT_MAX_CONCURRENCY = 50000
"""Default value for the maximum number of concurrent tests in the event loop."""
DEFAULT_NOFILE = 16384
"""Default value for the maximum number of open file descriptors for the ANTA process."""
class AntaRunnerSettings(BaseSettings):
"""Environment variables for configuring the ANTA runner.
When initialized, relevant environment variables are loaded. If not set, default values are used.
On POSIX systems, also adjusts the process soft limit based on the `ANTA_NOFILE` environment variable
while respecting the system hard limit, meaning the new soft limit cannot exceed the system's hard limit.
On non-POSIX systems (Windows), sets the limit to `sys.maxsize`.
The adjusted limit is available with the `file_descriptor_limit` property after initialization.
Attributes
----------
nofile : PositiveInt
Environment variable: ANTA_NOFILE
The maximum number of open file descriptors for the ANTA process. Defaults to 16384.
max_concurrency : PositiveInt
Environment variable: ANTA_MAX_CONCURRENCY
The maximum number of concurrent tests that can run in the event loop. Defaults to 50000.
"""
model_config = SettingsConfigDict(env_prefix="ANTA_")
nofile: PositiveInt = Field(default=DEFAULT_NOFILE)
max_concurrency: PositiveInt = Field(default=DEFAULT_MAX_CONCURRENCY)
# Computed in post-init
_file_descriptor_limit: PositiveInt
# pylint: disable=arguments-differ
def model_post_init(self, _context: Any) -> None: # noqa: ANN401
"""Post-initialization method to set the file descriptor limit for the current ANTA process."""
if os.name != "posix":
logger.warning("Running on a non-POSIX system, cannot adjust the maximum number of file descriptors.")
self._file_descriptor_limit = sys.maxsize
return
import resource
limits = resource.getrlimit(resource.RLIMIT_NOFILE)
logger.debug("Initial file descriptor limits for the current ANTA process: Soft Limit: %s | Hard Limit: %s", limits[0], limits[1])
# Set new soft limit to minimum of requested and hard limit
new_soft_limit = min(limits[1], self.nofile)
logger.debug("Setting file descriptor soft limit to %s", new_soft_limit)
try:
resource.setrlimit(resource.RLIMIT_NOFILE, (new_soft_limit, limits[1]))
except ValueError as exception:
logger.warning("Failed to set file descriptor soft limit for the current ANTA process: %s", exc_to_str(exception))
self._file_descriptor_limit = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
@property
def file_descriptor_limit(self) -> PositiveInt:
"""The maximum number of file descriptors available to the process."""
return self._file_descriptor_limit