diff --git a/common/library/modules/enable_telemetry_service.py b/common/library/modules/enable_telemetry_service.py index fe490c212a..a85c6da1b6 100644 --- a/common/library/modules/enable_telemetry_service.py +++ b/common/library/modules/enable_telemetry_service.py @@ -77,20 +77,80 @@ def get_report_definitions( return None +def enable_report( + session: requests.Session, + url: str, + user: str, + password: str, + timeout: int, +) -> bool: + """Enable a single telemetry report.""" + try: + data = { + "MetricReportDefinitionEnabled": True, + "Status": {"State": "Enabled"} + } + response = session.patch( + url, + json=data, + auth=(user, password), + verify=False, + timeout=timeout, + ) + return response.status_code in [200, 202, 204] + except requests.exceptions.RequestException: + return False + + +def enable_reports_parallel( + session: requests.Session, + base_url: str, + reports_to_enable: List[str], + user: str, + password: str, + timeout: int, + report_workers: int = 10, +) -> Tuple[List[str], List[str]]: + """Enable multiple reports in parallel.""" + enabled_reports: List[str] = [] + failed_reports: List[str] = [] + + report_urls = { + report: f"{base_url}/MetricReportDefinitions/{report}" + for report in reports_to_enable + } + + with ThreadPoolExecutor(max_workers=report_workers) as executor: + future_to_report = { + executor.submit(enable_report, session, url, user, password, timeout): report + for report, url in report_urls.items() + } + for future in as_completed(future_to_report): + report_name = future_to_report[future] + if future.result(): + enabled_reports.append(report_name) + else: + failed_reports.append(report_name) + + return enabled_reports, failed_reports + + def configure_server( ip_address: str, user: str, password: str, timeout: int, + exclude_reports: Optional[List[str]] = None, ) -> Dict[str, Any]: """Configure telemetry for a single server.""" session = requests.Session() session.verify = False + exclude_reports = exclude_reports or [] try: base_url = f"https://{ip_address}/redfish/v1/TelemetryService" - # Enable Telemetry Service + # Step 1: Enable Telemetry Service response = session.patch( base_url, json={"ServiceEnabled": True}, @@ -105,7 +165,7 @@ def configure_server( "message": f"Service HTTP {response.status_code}" } - # Get available reports + # Step 2: Get available reports available_reports = get_report_definitions( ip_address, user, password, session, timeout ) @@ -116,10 +176,27 @@ def configure_server( "message": "Cannot get reports" } + # Step 3: Filter out excluded reports + reports_to_enable = [ + r for r in available_reports if r not in exclude_reports + ] + skipped_reports = [ + r for r in available_reports if r in exclude_reports + ] + + # Step 4: Enable reports in parallel + enabled_reports, failed_reports = enable_reports_parallel( + session, base_url, reports_to_enable, user, password, timeout + ) + return { "ip": ip_address, "status": "success", - "enabled_reports": available_reports, + "message": f"{len(enabled_reports)}/{len(available_reports)} enabled", + "total_reports": len(available_reports), + "enabled_reports": enabled_reports, + "skipped_reports": skipped_reports, + "failed_reports": failed_reports, } except requests.exceptions.RequestException as e: @@ -141,6 +218,7 @@ def run_parallel( password: str, parallel_jobs: int, timeout: int, + exclude_reports: Optional[List[str]] = None, ) -> Tuple[List[Dict], List[Dict]]: """Run telemetry configuration in parallel.""" success_results = [] @@ -151,7 +229,7 @@ def run_parallel( with ThreadPoolExecutor(max_workers=workers) as executor: future_to_ip = { executor.submit( - configure_server, ip, username, password, timeout + configure_server, ip, username, password, timeout, exclude_reports ): ip for ip in idrac_ips } @@ -174,6 +252,7 @@ def main(): "password": {"type": "str", "required": True, "no_log": True}, "parallel_jobs": {"type": "int", "default": 64}, "timeout": {"type": "int", "default": 30}, + "exclude_reports": {"type": "list", "required": False, "elements": "str", "default": []}, } module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) @@ -183,6 +262,7 @@ def main(): password = module.params["password"] parallel_jobs = module.params["parallel_jobs"] timeout = module.params["timeout"] + exclude_reports = module.params["exclude_reports"] if module.check_mode: module.exit_json(changed=False, msg="Check mode - no changes made") @@ -192,19 +272,27 @@ def main(): start_time = time.time() success_results, failed_results = run_parallel( - idrac_ips, username, password, parallel_jobs, timeout + idrac_ips, username, password, parallel_jobs, timeout, exclude_reports ) duration = time.time() - start_time + # Calculate total reports enabled/failed + total_enabled = sum(len(r.get("enabled_reports", [])) for r in success_results) + total_failed = sum(len(r.get("failed_reports", [])) for r in success_results) + total_skipped = sum(len(r.get("skipped_reports", [])) for r in success_results) + module.exit_json( changed=len(success_results) > 0, success_count=len(success_results), failed_count=len(failed_results), + total_reports_enabled=total_enabled, + total_reports_failed=total_failed, + total_reports_skipped=total_skipped, duration_seconds=round(duration, 2), success_results=success_results, failed_results=failed_results, - msg=f"Telemetry enabled on {len(success_results)}/{len(idrac_ips)} servers" + msg=f"Telemetry enabled on {len(success_results)}/{len(idrac_ips)} servers ({total_enabled} reports)" ) if __name__ == "__main__":