Loading src/tests/mwc26-f5ga/AI_analytics_engine/__init__.py +0 −40 Original line number Diff line number Diff line Loading @@ -12,43 +12,3 @@ # See the License for the specific language governing permissions and # limitations under the License. """ AI Analytics Engine module. Provides REST API for AI-driven SLA policy analysis and violation detection using data from SIMAP (network topology/devices) and InfluxDB (telemetry metrics). Module Structure: - ai_model: AI/ML processing logic and SLA policy definitions - api: Flask REST API endpoints - clients: External service clients (SIMAP, InfluxDB, Decision Engine) - config: Configuration management - tests: Test suite Public API: - AIAnalyticsEngineAPI: Main orchestrator and Flask application - AIModelProcessor: AI/ML analysis engine - SLAPolicyConfig: SLA policy configuration data model - SimapDataFetcher: SIMAP client for device/topology data - InfluxDBFetcher: InfluxDB client for telemetry metrics - DecisionEngineClient: Decision engine notification client - create_ai_analytics_blueprint: Flask blueprint factory """ from .ai_model.ai_processor import AIModelProcessor from .api.api_blueprint import create_ai_analytics_blueprint from .engine import AIAnalyticsEngineAPI from .clients.decision_client import DecisionEngineClient from .clients.influxdb_fetcher import InfluxDBFetcher from .clients.simap_fetcher import SimapDataFetcher from .ai_model.sla_policy import SLAPolicyConfig __all__ = [ 'AIAnalyticsEngineAPI', 'AIModelProcessor', 'DecisionEngineClient', 'InfluxDBFetcher', 'SimapDataFetcher', 'SLAPolicyConfig', 'create_ai_analytics_blueprint', ] src/tests/mwc26-f5ga/AI_analytics_engine/tests/run_test.sh +12 −9 Original line number Diff line number Diff line Loading @@ -18,23 +18,26 @@ # Usage: ./run_test.sh # Navigate to TFS root directory cd "$(dirname "$0")/../../../../.." cd "$(dirname "$0")" # Set Python path to include TFS src and AI Analytics Engine export PYTHONPATH="${PWD}/src:${PWD}/src/tests/mwc26-f5ga" # export PYTHONPATH="${PWD}/src:${PWD}/src/tests/mwc26-f5ga" # Activate virtual environment if not already activated if [ -z "$VIRTUAL_ENV" ]; then if [ -d "$HOME/.env-simap" ]; then source "$HOME/.env-simap/bin/activate" fi fi # if [ -z "$VIRTUAL_ENV" ]; then # if [ -d "$HOME/.env-simap" ]; then # source "$HOME/.env-simap/bin/activate" # fi # fi echo "$PWD" echo "Running AI Analytics Engine API tests..." # Define log file path LOG_FILE="${PWD}/src/tests/mwc26-f5ga/AI_analytics_engine/tests/test_api.log" LOG_FILE="${PWD}/test_api_docker.log" TEST_FILE="${PWD}/test_api_docker.py" # Run the test with logging enabled and capture output pytest src/tests/mwc26-f5ga/AI_analytics_engine/tests/test_api.py::test_analyze_endpoint \ pytest $TEST_FILE \ -v -s \ --log-cli-level=DEBUG \ --log-file="${LOG_FILE}" \ Loading src/tests/mwc26-f5ga/AI_analytics_engine/tests/test_api_docker.py 0 → 100644 +142 −0 Original line number Diff line number Diff line # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Test suite for AI Analytics Engine REST API running in Docker. This module tests the /api/v1/analyze endpoint by connecting to the AI-Engine Docker container exposed on port 8084. """ import logging import time import pytest import requests # Configure logging for tests logging.basicConfig( level=logging.DEBUG, format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s" ) LOGGER = logging.getLogger(__name__) # Test server configuration - Docker container exposed port TEST_HOST = '127.0.0.1' TEST_PORT = 8084 # Docker container port mapping: 8084->8080 BASE_URL = f'http://{TEST_HOST}:{TEST_PORT}' @pytest.fixture(scope='module') def ai_engine_server(): """ Fixture to verify the AI Analytics Engine Docker container is running. Checks connectivity to the Docker container and yields control to tests. Assumes the container is already running (docker run -p 8084:8080 ai-engine:latest). """ LOGGER.info("Checking AI Analytics Engine Docker container availability") # Wait for server to be ready max_retries = 15 for i in range(max_retries): try: LOGGER.debug(f"Checking Docker container connectivity... ({i+1}/{max_retries})") response = requests.get(f'{BASE_URL}/api/v1/config', timeout=2) if response.status_code == 200: LOGGER.info("AI Analytics Engine Docker container is ready") break except requests.exceptions.RequestException as e: LOGGER.debug(f"Container not ready yet: {e}") if i < max_retries - 1: time.sleep(2) else: raise RuntimeError( f"Failed to connect to AI Analytics Engine Docker container at {BASE_URL}. " f"Ensure container is running: docker run -p 8084:8080 ai-engine:latest" ) yield LOGGER.info("AI Analytics Engine Docker test fixture cleanup complete") def test_analyze_endpoint(ai_engine_server): """ Test POST /api/v1/analyze endpoint. Validates that the analyze endpoint: - Accepts valid SLA policy JSON payload - Returns appropriate status codes (200 for success, 503 for service unavailable) - Returns JSON response with status and message fields """ LOGGER.info(">>>>>> Starting test_case test_analyze_endpoint: POST /api/v1/analyze endpoint") # Prepare test payload with SLA policy configuration payload = { "simap_id": "E2E-L1", "sla_metrics": { "latency_threshold_ms": 0, "bandwidth_utilization": 0.0 }, "history_window_size_sec": 600, "forecast_sample_interval_sec": 5, "forecast_sample_count": 120, } LOGGER.info(f"Sending analyze request with payload: {payload}") # Send POST request to analyze endpoint response = requests.post( f'{BASE_URL}/api/v1/analyze', json=payload, timeout=10 ) # Add condition to validate response status code and content LOGGER.info(f"Analyze response status: {response.status_code}") # Parse JSON response data = response.json() LOGGER.info(f"Analyze response body: {data}") # Validate response structure assert 'status' in data, "Response missing 'status' field" assert 'message' in data, "Response missing 'message' field" # Accept either success (200) or service unavailable (503) # 503 is expected if SIMAP server or InfluxDB are not running if response.status_code == 200: LOGGER.info("Analysis completed successfully") assert data['status'] == 'success', f"Expected status 'success', got '{data['status']}'" assert 'data' in data, "Successful response missing 'data' field" elif response.status_code == 503: # LOGGER.error("External service unavailable (expected if SIMAP/InfluxDB not running)") assert data['status'] == 'error', f"Expected status 'error' for 503, got '{data['status']}'" pytest.fail("External service unavailable (expected if SIMAP/InfluxDB not running)") elif response.status_code == 400: LOGGER.error(f"Bad request: {data['message']}") assert data['status'] == 'error', f"Expected status 'error' for 400, got '{data['status']}'" pytest.fail(f"Bad request: {data['message']}") else: pytest.fail(f"Unexpected status code: {response.status_code}") LOGGER.info("Analyze endpoint test passed!") LOGGER.info("<<<<<< Finished test_case test_analyze_endpoint") src/tests/mwc26-f5ga/deploy.sh +12 −12 Original line number Diff line number Diff line Loading @@ -5,23 +5,23 @@ echo "Building SIMAP Server..." cd ~/tfs-ctrl/ docker buildx build -t simap-server:mock -f ./src/tests/tools/simap_server/Dockerfile . # echo "Building NCE-FAN Controller..." # cd ~/tfs-ctrl/ # docker buildx build -t nce-fan-ctrl:mock -f ./src/tests/tools/mock_nce_fan_ctrl/Dockerfile . echo "Building NCE-FAN Controller..." cd ~/tfs-ctrl/ docker buildx build -t nce-fan-ctrl:mock -f ./src/tests/tools/mock_nce_fan_ctrl/Dockerfile . # echo "Building NCE-T Controller..." # cd ~/tfs-ctrl/ # docker buildx build -t nce-t-ctrl:mock -f ./src/tests/tools/mock_nce_t_ctrl/Dockerfile . echo "Building NCE-T Controller..." cd ~/tfs-ctrl/ docker buildx build -t nce-t-ctrl:mock -f ./src/tests/tools/mock_nce_t_ctrl/Dockerfile . echo "Building AI Analytics Engine..." cd ~/tfs-ctrl/ docker buildx build -t ai-engine:latest -f ./src/tests/mwc26-f5ga/AI_analytics_engine/Dockerfile . # echo "Cleaning up..." echo "Cleaning up..." docker rm --force simap-server # docker rm --force nce-fan-ctrl # docker rm --force nce-t-ctrl docker rm --force nce-fan-ctrl docker rm --force nce-t-ctrl docker rm --force ai-engine # echo "Deploying support services..." Loading @@ -29,8 +29,9 @@ docker run --detach --name simap-server --publish 8080:8080 \ -e INFLUXDB_HOST=10.254.0.9 \ -e INFLUXDB_PORT=8181 \ simap-server:mock # docker run --detach --name nce-fan-ctrl --publish 8081:8080 --env SIMAP_ADDRESS=172.17.0.1 --env SIMAP_PORT=8080 nce-fan-ctrl:mock # docker run --detach --name nce-t-ctrl --publish 8082:8080 --env SIMAP_ADDRESS=172.17.0.1 --env SIMAP_PORT=8080 nce-t-ctrl:mock docker run --detach --name nce-fan-ctrl --publish 8081:8080 --env SIMAP_ADDRESS=172.17.0.1 --env SIMAP_PORT=8080 nce-fan-ctrl:mock docker run --detach --name nce-t-ctrl --publish 8082:8080 --env SIMAP_ADDRESS=172.17.0.1 --env SIMAP_PORT=8080 nce-t-ctrl:mock echo "Deploying AI Analytics Engine..." docker run --detach --name ai-engine --publish 8084:8080 \ Loading @@ -43,7 +44,6 @@ docker run --detach --name ai-engine --publish 8084:8080 \ # NOTE: If testing, run client (src/tests/tools/simap_server/run_client.sh) to manually populate SIMAP Server with telemetry data. sleep 2 docker ps -a echo "Deployment complete." src/tests/mwc26-f5ga/deploy_ai_engine.shdeleted 100755 → 0 +0 −20 Original line number Diff line number Diff line docker rm --force ai-engine 2>/dev/null || true echo "Building AI Analytics Engine..." cd ~/tfs-ctrl/ docker buildx build -t ai-engine:latest -f ./src/tests/mwc26-f5ga/AI_analytics_engine/Dockerfile . echo "Deploying AI Analytics Engine..." docker run --detach --name ai-engine \ --publish 8084:8080 \ --env SIMAP_SERVER_ADDRESS=172.17.0.1 \ --env SIMAP_SERVER_PORT=8080 \ --env SIMAP_SERVER_USERNAME=admin \ --env SIMAP_SERVER_PASSWORD=admin \ ai-engine:latest # docker run --detach --name traffic-changer --publish 8083:8080 traffic-changer:mock sleep 2 docker ps -a echo "Deployment complete." Loading
src/tests/mwc26-f5ga/AI_analytics_engine/__init__.py +0 −40 Original line number Diff line number Diff line Loading @@ -12,43 +12,3 @@ # See the License for the specific language governing permissions and # limitations under the License. """ AI Analytics Engine module. Provides REST API for AI-driven SLA policy analysis and violation detection using data from SIMAP (network topology/devices) and InfluxDB (telemetry metrics). Module Structure: - ai_model: AI/ML processing logic and SLA policy definitions - api: Flask REST API endpoints - clients: External service clients (SIMAP, InfluxDB, Decision Engine) - config: Configuration management - tests: Test suite Public API: - AIAnalyticsEngineAPI: Main orchestrator and Flask application - AIModelProcessor: AI/ML analysis engine - SLAPolicyConfig: SLA policy configuration data model - SimapDataFetcher: SIMAP client for device/topology data - InfluxDBFetcher: InfluxDB client for telemetry metrics - DecisionEngineClient: Decision engine notification client - create_ai_analytics_blueprint: Flask blueprint factory """ from .ai_model.ai_processor import AIModelProcessor from .api.api_blueprint import create_ai_analytics_blueprint from .engine import AIAnalyticsEngineAPI from .clients.decision_client import DecisionEngineClient from .clients.influxdb_fetcher import InfluxDBFetcher from .clients.simap_fetcher import SimapDataFetcher from .ai_model.sla_policy import SLAPolicyConfig __all__ = [ 'AIAnalyticsEngineAPI', 'AIModelProcessor', 'DecisionEngineClient', 'InfluxDBFetcher', 'SimapDataFetcher', 'SLAPolicyConfig', 'create_ai_analytics_blueprint', ]
src/tests/mwc26-f5ga/AI_analytics_engine/tests/run_test.sh +12 −9 Original line number Diff line number Diff line Loading @@ -18,23 +18,26 @@ # Usage: ./run_test.sh # Navigate to TFS root directory cd "$(dirname "$0")/../../../../.." cd "$(dirname "$0")" # Set Python path to include TFS src and AI Analytics Engine export PYTHONPATH="${PWD}/src:${PWD}/src/tests/mwc26-f5ga" # export PYTHONPATH="${PWD}/src:${PWD}/src/tests/mwc26-f5ga" # Activate virtual environment if not already activated if [ -z "$VIRTUAL_ENV" ]; then if [ -d "$HOME/.env-simap" ]; then source "$HOME/.env-simap/bin/activate" fi fi # if [ -z "$VIRTUAL_ENV" ]; then # if [ -d "$HOME/.env-simap" ]; then # source "$HOME/.env-simap/bin/activate" # fi # fi echo "$PWD" echo "Running AI Analytics Engine API tests..." # Define log file path LOG_FILE="${PWD}/src/tests/mwc26-f5ga/AI_analytics_engine/tests/test_api.log" LOG_FILE="${PWD}/test_api_docker.log" TEST_FILE="${PWD}/test_api_docker.py" # Run the test with logging enabled and capture output pytest src/tests/mwc26-f5ga/AI_analytics_engine/tests/test_api.py::test_analyze_endpoint \ pytest $TEST_FILE \ -v -s \ --log-cli-level=DEBUG \ --log-file="${LOG_FILE}" \ Loading
src/tests/mwc26-f5ga/AI_analytics_engine/tests/test_api_docker.py 0 → 100644 +142 −0 Original line number Diff line number Diff line # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Test suite for AI Analytics Engine REST API running in Docker. This module tests the /api/v1/analyze endpoint by connecting to the AI-Engine Docker container exposed on port 8084. """ import logging import time import pytest import requests # Configure logging for tests logging.basicConfig( level=logging.DEBUG, format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s" ) LOGGER = logging.getLogger(__name__) # Test server configuration - Docker container exposed port TEST_HOST = '127.0.0.1' TEST_PORT = 8084 # Docker container port mapping: 8084->8080 BASE_URL = f'http://{TEST_HOST}:{TEST_PORT}' @pytest.fixture(scope='module') def ai_engine_server(): """ Fixture to verify the AI Analytics Engine Docker container is running. Checks connectivity to the Docker container and yields control to tests. Assumes the container is already running (docker run -p 8084:8080 ai-engine:latest). """ LOGGER.info("Checking AI Analytics Engine Docker container availability") # Wait for server to be ready max_retries = 15 for i in range(max_retries): try: LOGGER.debug(f"Checking Docker container connectivity... ({i+1}/{max_retries})") response = requests.get(f'{BASE_URL}/api/v1/config', timeout=2) if response.status_code == 200: LOGGER.info("AI Analytics Engine Docker container is ready") break except requests.exceptions.RequestException as e: LOGGER.debug(f"Container not ready yet: {e}") if i < max_retries - 1: time.sleep(2) else: raise RuntimeError( f"Failed to connect to AI Analytics Engine Docker container at {BASE_URL}. " f"Ensure container is running: docker run -p 8084:8080 ai-engine:latest" ) yield LOGGER.info("AI Analytics Engine Docker test fixture cleanup complete") def test_analyze_endpoint(ai_engine_server): """ Test POST /api/v1/analyze endpoint. Validates that the analyze endpoint: - Accepts valid SLA policy JSON payload - Returns appropriate status codes (200 for success, 503 for service unavailable) - Returns JSON response with status and message fields """ LOGGER.info(">>>>>> Starting test_case test_analyze_endpoint: POST /api/v1/analyze endpoint") # Prepare test payload with SLA policy configuration payload = { "simap_id": "E2E-L1", "sla_metrics": { "latency_threshold_ms": 0, "bandwidth_utilization": 0.0 }, "history_window_size_sec": 600, "forecast_sample_interval_sec": 5, "forecast_sample_count": 120, } LOGGER.info(f"Sending analyze request with payload: {payload}") # Send POST request to analyze endpoint response = requests.post( f'{BASE_URL}/api/v1/analyze', json=payload, timeout=10 ) # Add condition to validate response status code and content LOGGER.info(f"Analyze response status: {response.status_code}") # Parse JSON response data = response.json() LOGGER.info(f"Analyze response body: {data}") # Validate response structure assert 'status' in data, "Response missing 'status' field" assert 'message' in data, "Response missing 'message' field" # Accept either success (200) or service unavailable (503) # 503 is expected if SIMAP server or InfluxDB are not running if response.status_code == 200: LOGGER.info("Analysis completed successfully") assert data['status'] == 'success', f"Expected status 'success', got '{data['status']}'" assert 'data' in data, "Successful response missing 'data' field" elif response.status_code == 503: # LOGGER.error("External service unavailable (expected if SIMAP/InfluxDB not running)") assert data['status'] == 'error', f"Expected status 'error' for 503, got '{data['status']}'" pytest.fail("External service unavailable (expected if SIMAP/InfluxDB not running)") elif response.status_code == 400: LOGGER.error(f"Bad request: {data['message']}") assert data['status'] == 'error', f"Expected status 'error' for 400, got '{data['status']}'" pytest.fail(f"Bad request: {data['message']}") else: pytest.fail(f"Unexpected status code: {response.status_code}") LOGGER.info("Analyze endpoint test passed!") LOGGER.info("<<<<<< Finished test_case test_analyze_endpoint")
src/tests/mwc26-f5ga/deploy.sh +12 −12 Original line number Diff line number Diff line Loading @@ -5,23 +5,23 @@ echo "Building SIMAP Server..." cd ~/tfs-ctrl/ docker buildx build -t simap-server:mock -f ./src/tests/tools/simap_server/Dockerfile . # echo "Building NCE-FAN Controller..." # cd ~/tfs-ctrl/ # docker buildx build -t nce-fan-ctrl:mock -f ./src/tests/tools/mock_nce_fan_ctrl/Dockerfile . echo "Building NCE-FAN Controller..." cd ~/tfs-ctrl/ docker buildx build -t nce-fan-ctrl:mock -f ./src/tests/tools/mock_nce_fan_ctrl/Dockerfile . # echo "Building NCE-T Controller..." # cd ~/tfs-ctrl/ # docker buildx build -t nce-t-ctrl:mock -f ./src/tests/tools/mock_nce_t_ctrl/Dockerfile . echo "Building NCE-T Controller..." cd ~/tfs-ctrl/ docker buildx build -t nce-t-ctrl:mock -f ./src/tests/tools/mock_nce_t_ctrl/Dockerfile . echo "Building AI Analytics Engine..." cd ~/tfs-ctrl/ docker buildx build -t ai-engine:latest -f ./src/tests/mwc26-f5ga/AI_analytics_engine/Dockerfile . # echo "Cleaning up..." echo "Cleaning up..." docker rm --force simap-server # docker rm --force nce-fan-ctrl # docker rm --force nce-t-ctrl docker rm --force nce-fan-ctrl docker rm --force nce-t-ctrl docker rm --force ai-engine # echo "Deploying support services..." Loading @@ -29,8 +29,9 @@ docker run --detach --name simap-server --publish 8080:8080 \ -e INFLUXDB_HOST=10.254.0.9 \ -e INFLUXDB_PORT=8181 \ simap-server:mock # docker run --detach --name nce-fan-ctrl --publish 8081:8080 --env SIMAP_ADDRESS=172.17.0.1 --env SIMAP_PORT=8080 nce-fan-ctrl:mock # docker run --detach --name nce-t-ctrl --publish 8082:8080 --env SIMAP_ADDRESS=172.17.0.1 --env SIMAP_PORT=8080 nce-t-ctrl:mock docker run --detach --name nce-fan-ctrl --publish 8081:8080 --env SIMAP_ADDRESS=172.17.0.1 --env SIMAP_PORT=8080 nce-fan-ctrl:mock docker run --detach --name nce-t-ctrl --publish 8082:8080 --env SIMAP_ADDRESS=172.17.0.1 --env SIMAP_PORT=8080 nce-t-ctrl:mock echo "Deploying AI Analytics Engine..." docker run --detach --name ai-engine --publish 8084:8080 \ Loading @@ -43,7 +44,6 @@ docker run --detach --name ai-engine --publish 8084:8080 \ # NOTE: If testing, run client (src/tests/tools/simap_server/run_client.sh) to manually populate SIMAP Server with telemetry data. sleep 2 docker ps -a echo "Deployment complete."
src/tests/mwc26-f5ga/deploy_ai_engine.shdeleted 100755 → 0 +0 −20 Original line number Diff line number Diff line docker rm --force ai-engine 2>/dev/null || true echo "Building AI Analytics Engine..." cd ~/tfs-ctrl/ docker buildx build -t ai-engine:latest -f ./src/tests/mwc26-f5ga/AI_analytics_engine/Dockerfile . echo "Deploying AI Analytics Engine..." docker run --detach --name ai-engine \ --publish 8084:8080 \ --env SIMAP_SERVER_ADDRESS=172.17.0.1 \ --env SIMAP_SERVER_PORT=8080 \ --env SIMAP_SERVER_USERNAME=admin \ --env SIMAP_SERVER_PASSWORD=admin \ ai-engine:latest # docker run --detach --name traffic-changer --publish 8083:8080 traffic-changer:mock sleep 2 docker ps -a echo "Deployment complete."