Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 94 additions & 6 deletions common/library/modules/enable_telemetry_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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
)
Expand All @@ -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:
Expand All @@ -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 = []
Expand All @@ -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
}

Expand All @@ -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)
Expand All @@ -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")
Expand All @@ -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__":
Expand Down