2024-12-04 20:46:35 -05:00
|
|
|
#!/usr/bin/env python3
|
2024-12-05 20:18:14 -05:00
|
|
|
import os, sys, json, requests, psutil, socket, subprocess, logging
|
2024-12-04 20:46:35 -05:00
|
|
|
from typing import Dict, Any, List
|
|
|
|
|
|
2024-12-05 15:30:16 -05:00
|
|
|
# Create a logger
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
|
|
|
|
|
|
# Create a console handler and set its level to DEBUG
|
|
|
|
|
console_handler = logging.StreamHandler()
|
|
|
|
|
console_handler.setLevel(logging.DEBUG)
|
|
|
|
|
|
|
|
|
|
# Create a formatter
|
|
|
|
|
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
|
|
|
|
|
|
|
|
|
|
# Add the formatter to the console handler
|
|
|
|
|
console_handler.setFormatter(formatter)
|
|
|
|
|
|
|
|
|
|
# Add the console handler to the logger
|
|
|
|
|
logger.addHandler(console_handler)
|
|
|
|
|
|
2024-12-04 20:46:35 -05:00
|
|
|
class SystemHealthMonitor:
|
|
|
|
|
def __init__(self,
|
|
|
|
|
ticket_api_url: str = 'http://10.10.10.45/create_ticket_api.php',
|
|
|
|
|
state_file: str = '/tmp/last_health_check.json'):
|
|
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
Initialize the system health monitor.
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
:param ticket_api_url: URL for the ticket creation API.
|
|
|
|
|
:param state_file: File path to track the last health check results.
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
|
|
|
|
self.ticket_api_url = ticket_api_url
|
|
|
|
|
self.state_file = state_file
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
Perform a one-shot health check of the system.
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
|
|
|
|
try:
|
2024-12-04 21:55:33 -05:00
|
|
|
# Perform health checks and gather the report
|
2024-12-04 20:46:35 -05:00
|
|
|
health_report = self.perform_health_checks()
|
|
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
# Create tickets for any detected critical issues
|
2024-12-04 20:46:35 -05:00
|
|
|
self._create_tickets_for_issues(health_report)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Unexpected error during health check: {e}")
|
|
|
|
|
|
|
|
|
|
def perform_health_checks(self) -> Dict[str, Any]:
|
|
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
Perform comprehensive system health checks and return a report.
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
:return: Dictionary containing results of various health checks.
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
|
|
|
|
health_report = {
|
2024-12-04 21:20:52 -05:00
|
|
|
'drives_health': self._check_drives_health(),
|
2024-12-04 20:46:35 -05:00
|
|
|
'memory_health': self._check_memory_usage(),
|
|
|
|
|
'cpu_health': self._check_cpu_usage(),
|
2024-12-04 21:43:10 -05:00
|
|
|
'network_health': self._check_network_status()
|
2024-12-04 20:46:35 -05:00
|
|
|
}
|
|
|
|
|
return health_report
|
|
|
|
|
|
2024-12-05 15:30:16 -05:00
|
|
|
def _generate_detailed_description(self, issue: str, health_report: Dict[str, Any]) -> str:
|
|
|
|
|
"""
|
|
|
|
|
Generate a detailed description for the issue based on the health report.
|
|
|
|
|
|
|
|
|
|
:param issue: The issue description.
|
|
|
|
|
:param health_report: The comprehensive health report from the checks.
|
|
|
|
|
:return: A detailed description for the issue.
|
|
|
|
|
"""
|
|
|
|
|
description = issue + "\n\n"
|
|
|
|
|
|
|
|
|
|
if "Disk" in issue:
|
|
|
|
|
for partition in health_report.get('drives_health', {}).get('drives', []):
|
|
|
|
|
if partition.get('mountpoint') in issue:
|
|
|
|
|
description += f"Disk Device: {partition['device']}\n"
|
|
|
|
|
description += f"Mount Point: {partition['mountpoint']}\n"
|
|
|
|
|
description += f"Total Space: {partition['total_space']}\n"
|
|
|
|
|
description += f"Used Space: {partition['used_space']}\n"
|
|
|
|
|
description += f"Free Space: {partition['free_space']}\n"
|
|
|
|
|
description += f"Usage Percent: {partition['usage_percent']}%\n"
|
|
|
|
|
|
|
|
|
|
if partition.get('smart_status') == 'UNHEALTHY':
|
|
|
|
|
try:
|
|
|
|
|
# Get additional disk information using smartctl
|
|
|
|
|
result = subprocess.run(
|
|
|
|
|
['smartctl', '-a', partition['device']],
|
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
|
stderr=subprocess.PIPE,
|
|
|
|
|
text=True
|
|
|
|
|
)
|
|
|
|
|
output = result.stdout + result.stderr
|
|
|
|
|
description += "\nSMART Information:\n"
|
|
|
|
|
description += output
|
|
|
|
|
except Exception as e:
|
|
|
|
|
description += f"Error getting SMART information: {str(e)}\n"
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
elif "Memory" in issue:
|
|
|
|
|
memory_health = health_report.get('memory_health', {})
|
|
|
|
|
description += f"Total Memory: {memory_health['total_memory']}\n"
|
|
|
|
|
description += f"Used Memory: {memory_health['used_memory']}\n"
|
|
|
|
|
description += f"Memory Usage Percent: {memory_health['memory_percent']}%\n"
|
|
|
|
|
|
|
|
|
|
elif "CPU" in issue:
|
|
|
|
|
cpu_health = health_report.get('cpu_health', {})
|
|
|
|
|
description += f"CPU Usage Percent: {cpu_health['cpu_usage_percent']}%\n"
|
|
|
|
|
|
|
|
|
|
elif "Network" in issue:
|
|
|
|
|
network_health = health_report.get('network_health', {})
|
|
|
|
|
for network in ['management_network', 'ceph_network']:
|
|
|
|
|
if network_health[network]['issues']:
|
|
|
|
|
description += f"{network.replace('_', ' ').title()} Issues:\n"
|
|
|
|
|
description += "\n".join(network_health[network]['issues'])
|
|
|
|
|
description += "\n"
|
|
|
|
|
|
|
|
|
|
return description
|
|
|
|
|
|
2024-12-04 20:46:35 -05:00
|
|
|
def _create_tickets_for_issues(self, health_report: Dict[str, Any]):
|
|
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
Create tickets for detected issues with dynamic parameters based on severity.
|
|
|
|
|
|
|
|
|
|
:param health_report: The comprehensive health report from the checks.
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
issues = self._detect_issues(health_report)
|
|
|
|
|
if not issues:
|
|
|
|
|
print("No issues detected.")
|
2024-12-04 20:46:35 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# Initialize default ticket fields
|
2024-12-04 21:55:33 -05:00
|
|
|
hostname = socket.gethostname() # Get the current hostname
|
|
|
|
|
action_type = "[auto]" # Default action type for automatic checks
|
|
|
|
|
scope = "[cluster-wide]" # Scope of the issues
|
|
|
|
|
environment = "[production]" # Environment where the issues were found
|
|
|
|
|
ticket_type = "[maintenance]" # Type of the ticket being created
|
|
|
|
|
|
|
|
|
|
for issue in issues:
|
|
|
|
|
# Determine priority, category, and type based on the issue detected
|
2024-12-04 22:00:59 -05:00
|
|
|
priority = "4" # Default to low priority
|
2024-12-04 21:55:33 -05:00
|
|
|
category = "Other"
|
|
|
|
|
issue_type = "Task"
|
|
|
|
|
|
|
|
|
|
if "Disk" in issue:
|
2024-12-04 22:00:59 -05:00
|
|
|
priority = "3" # Medium priority for disk issues
|
2024-12-04 21:55:33 -05:00
|
|
|
category = "Hardware"
|
|
|
|
|
issue_type = "Incident"
|
|
|
|
|
elif "Memory" in issue:
|
2024-12-04 22:00:59 -05:00
|
|
|
priority = "4" # Low priority for memory issues
|
2024-12-04 21:55:33 -05:00
|
|
|
category = "Hardware"
|
|
|
|
|
issue_type = "Incident"
|
|
|
|
|
elif "CPU" in issue:
|
2024-12-04 22:00:59 -05:00
|
|
|
priority = "4" # Low priority for CPU issues
|
2024-12-04 21:55:33 -05:00
|
|
|
category = "Hardware"
|
|
|
|
|
issue_type = "Incident"
|
|
|
|
|
elif "issues" in issue: # Any network issues
|
2024-12-04 22:00:59 -05:00
|
|
|
priority = "2" # High priority for network issues
|
2024-12-04 21:55:33 -05:00
|
|
|
category = "Network"
|
|
|
|
|
issue_type = "Problem"
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
# Create the ticket title with relevant details
|
|
|
|
|
ticket_title = f"[{hostname}]{action_type}[{issue_type}] {issue} {scope}{environment}{ticket_type}"
|
2024-12-05 15:30:16 -05:00
|
|
|
# Create a detailed description for the ticket
|
|
|
|
|
description = self._generate_detailed_description(issue, health_report)
|
|
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
ticket_payload = {
|
|
|
|
|
"title": ticket_title,
|
2024-12-05 15:30:16 -05:00
|
|
|
"description": description,
|
2024-12-04 21:55:33 -05:00
|
|
|
"priority": priority,
|
|
|
|
|
"status": "Open",
|
|
|
|
|
"category": category,
|
|
|
|
|
"type": issue_type
|
|
|
|
|
}
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:58:51 -05:00
|
|
|
# Debug: Log the ticket payload being sent
|
|
|
|
|
print("Attempting to create ticket with payload:")
|
|
|
|
|
print(json.dumps(ticket_payload, indent=4))
|
|
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
# Attempt to create the ticket via the API
|
|
|
|
|
try:
|
|
|
|
|
response = requests.post(
|
|
|
|
|
self.ticket_api_url,
|
|
|
|
|
json=ticket_payload,
|
|
|
|
|
headers={'Content-Type': 'application/json'}
|
|
|
|
|
)
|
2024-12-04 21:58:51 -05:00
|
|
|
|
|
|
|
|
# Debug: Log the response from the server
|
|
|
|
|
print(f"Response status code: {response.status_code}")
|
|
|
|
|
print(f"Response body: {response.text}")
|
|
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
if response.status_code in [200, 201]:
|
|
|
|
|
print(f"Ticket created successfully: {ticket_title}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"Failed to create ticket. Status code: {response.status_code}")
|
|
|
|
|
print(f"Response: {response.text}")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Error creating ticket: {e}")
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
def _detect_issues(self, health_report: Dict[str, Any]) -> List[str]:
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
Detect issues in the health report including non-critical issues.
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
:param health_report: The comprehensive health report from the checks.
|
|
|
|
|
:return: List of issue descriptions detected during checks.
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
issues = []
|
|
|
|
|
|
|
|
|
|
# Check for drive-related issues
|
|
|
|
|
for partition in health_report.get('drives_health', {}).get('drives', []):
|
|
|
|
|
if partition.get('usage_status') == 'CRITICAL_HIGH_USAGE':
|
|
|
|
|
issues.append(
|
2024-12-04 20:46:35 -05:00
|
|
|
f"Disk {partition['mountpoint']} is {partition['usage_percent']}% full"
|
|
|
|
|
)
|
2024-12-04 21:55:33 -05:00
|
|
|
elif partition.get('usage_status') == 'WARNING_HIGH_USAGE':
|
|
|
|
|
issues.append(
|
|
|
|
|
f"Disk {partition['mountpoint']} is {partition['usage_percent']}% full (Warning)"
|
|
|
|
|
)
|
|
|
|
|
if partition.get('smart_status') == 'UNHEALTHY':
|
|
|
|
|
issues.append(f"Disk {partition['mountpoint']} has an unhealthy SMART status")
|
|
|
|
|
|
|
|
|
|
# Check for memory-related issues
|
|
|
|
|
memory_health = health_report.get('memory_health', {})
|
|
|
|
|
if memory_health and memory_health.get('memory_percent', 0) > 80:
|
|
|
|
|
issues.append("Memory usage is above 80%")
|
|
|
|
|
|
|
|
|
|
# Check for CPU-related issues
|
|
|
|
|
cpu_health = health_report.get('cpu_health', {})
|
|
|
|
|
if cpu_health and cpu_health.get('cpu_usage_percent', 0) > 80:
|
|
|
|
|
issues.append("CPU usage is above 80%")
|
|
|
|
|
|
|
|
|
|
# Check for network-related issues
|
|
|
|
|
network_health = health_report.get('network_health', {})
|
|
|
|
|
for network in ['management_network', 'ceph_network']:
|
|
|
|
|
if network_health.get(network, {}).get('issues'):
|
|
|
|
|
issues.extend(network_health[network]['issues'])
|
|
|
|
|
|
|
|
|
|
return issues
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:20:52 -05:00
|
|
|
def _check_drives_health(self) -> Dict[str, Any]:
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
2024-12-04 21:20:52 -05:00
|
|
|
Check overall health of drives including disk usage and SMART status.
|
2024-12-05 15:30:16 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
:return: Combined health report of all drives and their status.
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
2024-12-04 21:20:52 -05:00
|
|
|
drives_health = {'overall_status': 'NORMAL', 'drives': []}
|
2024-12-04 20:46:35 -05:00
|
|
|
try:
|
|
|
|
|
partitions = psutil.disk_partitions()
|
2024-12-04 21:20:52 -05:00
|
|
|
overall_status = 'NORMAL'
|
2024-12-04 20:46:35 -05:00
|
|
|
for partition in partitions:
|
2024-12-04 21:20:52 -05:00
|
|
|
drive_report = {
|
|
|
|
|
'device': partition.device,
|
|
|
|
|
'mountpoint': partition.mountpoint
|
|
|
|
|
}
|
2024-12-04 20:46:35 -05:00
|
|
|
try:
|
2024-12-04 21:55:33 -05:00
|
|
|
# Check disk usage
|
2024-12-04 20:46:35 -05:00
|
|
|
usage = psutil.disk_usage(partition.mountpoint)
|
2024-12-05 15:30:16 -05:00
|
|
|
disk_usage_status = 'NORMAL'
|
2024-12-04 21:20:52 -05:00
|
|
|
if usage.percent > 90:
|
2024-12-05 15:30:16 -05:00
|
|
|
disk_usage_status = 'CRITICAL_HIGH_USAGE'
|
2024-12-04 21:20:52 -05:00
|
|
|
elif usage.percent > 80:
|
2024-12-05 15:30:16 -05:00
|
|
|
disk_usage_status = 'WARNING_HIGH_USAGE'
|
2024-12-04 21:20:52 -05:00
|
|
|
drive_report.update({
|
2024-12-04 20:46:35 -05:00
|
|
|
'total_space': self._convert_bytes(usage.total),
|
|
|
|
|
'used_space': self._convert_bytes(usage.used),
|
|
|
|
|
'free_space': self._convert_bytes(usage.free),
|
2024-12-04 21:20:52 -05:00
|
|
|
'usage_percent': usage.percent,
|
2024-12-05 20:18:14 -05:00
|
|
|
'usage_status': disk_usage_status
|
2024-12-04 21:20:52 -05:00
|
|
|
})
|
2024-12-04 21:55:33 -05:00
|
|
|
# Update overall status based on usage
|
2024-12-05 15:30:16 -05:00
|
|
|
if disk_usage_status == 'CRITICAL_HIGH_USAGE':
|
2024-12-04 21:20:52 -05:00
|
|
|
overall_status = 'CRITICAL_HIGH_USAGE'
|
2024-12-05 15:30:16 -05:00
|
|
|
elif disk_usage_status == 'WARNING_HIGH_USAGE' and overall_status != 'CRITICAL_HIGH_USAGE':
|
2024-12-04 21:20:52 -05:00
|
|
|
overall_status = 'WARNING_HIGH_USAGE'
|
2024-12-04 21:55:33 -05:00
|
|
|
# Check SMART status of the drive
|
2024-12-04 21:20:52 -05:00
|
|
|
try:
|
|
|
|
|
result = subprocess.run(
|
2024-12-05 20:24:10 -05:00
|
|
|
['smartctl', '-H', '-d', 'auto', partition.device],
|
2024-12-04 21:20:52 -05:00
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
|
stderr=subprocess.PIPE,
|
|
|
|
|
text=True
|
|
|
|
|
)
|
|
|
|
|
output = result.stdout + result.stderr
|
2024-12-05 15:30:16 -05:00
|
|
|
drive_smart_status = 'HEALTHY' if 'PASSED' in output else 'UNHEALTHY'
|
2024-12-05 20:18:14 -05:00
|
|
|
drive_report['smart_status'] = drive_smart_status
|
2024-12-04 21:55:33 -05:00
|
|
|
# Update overall status if SMART status is unhealthy
|
2024-12-05 15:30:16 -05:00
|
|
|
if drive_smart_status == 'UNHEALTHY' and overall_status != 'CRITICAL_HIGH_USAGE':
|
2024-12-04 21:20:52 -05:00
|
|
|
overall_status = 'UNHEALTHY'
|
|
|
|
|
except Exception as e:
|
2024-12-04 21:55:33 -05:00
|
|
|
print(f"Error checking SMART status for {partition.device}: {str(e)}")
|
2024-12-05 20:18:14 -05:00
|
|
|
drive_report['smart_status'] = 'ERROR'
|
2024-12-04 20:46:35 -05:00
|
|
|
except Exception as e:
|
2024-12-05 15:30:16 -05:00
|
|
|
logger.error(f"Could not check drive: {str(e)}")
|
|
|
|
|
drive_report['error'] = str(e)
|
2024-12-04 21:20:52 -05:00
|
|
|
drives_health['drives'].append(drive_report)
|
|
|
|
|
drives_health['overall_status'] = overall_status
|
2024-12-05 15:36:02 -05:00
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"Error checking drives health: {str(e)}")
|
|
|
|
|
return drives_health
|
2024-12-04 21:20:52 -05:00
|
|
|
|
2024-12-05 20:18:14 -05:00
|
|
|
@staticmethod
|
2024-12-05 15:30:16 -05:00
|
|
|
def _convert_bytes(bytes_value: int, suffix: str = 'B') -> str:
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
Convert bytes to a human-readable format.
|
2024-12-05 15:30:16 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
:param bytes_value: Number of bytes to convert.
|
|
|
|
|
:param suffix: Suffix to append (default is 'B' for bytes).
|
|
|
|
|
:return: Formatted string with the size in human-readable form.
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
|
|
|
|
for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
|
|
|
|
|
if abs(bytes_value) < 1024.0:
|
|
|
|
|
return f"{bytes_value:.1f}{unit}{suffix}"
|
|
|
|
|
bytes_value /= 1024.0
|
|
|
|
|
return f"{bytes_value:.1f}Y{suffix}"
|
|
|
|
|
|
|
|
|
|
def _check_memory_usage(self) -> Dict[str, Any]:
|
|
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
Check memory usage and return health metrics.
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
:return: Dictionary with memory health metrics.
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
memory_info = psutil.virtual_memory()
|
|
|
|
|
memory_health = {
|
|
|
|
|
'total_memory': self._convert_bytes(memory_info.total),
|
|
|
|
|
'used_memory': self._convert_bytes(memory_info.used),
|
|
|
|
|
'memory_percent': memory_info.percent,
|
2024-12-05 15:30:16 -05:00
|
|
|
'status': 'OK' if memory_info.percent < 90 else 'WARNING'
|
2024-12-04 21:55:33 -05:00
|
|
|
}
|
|
|
|
|
return memory_health
|
2024-12-04 20:46:35 -05:00
|
|
|
|
|
|
|
|
def _check_cpu_usage(self) -> Dict[str, Any]:
|
|
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
Check CPU usage and return health metrics.
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
:return: Dictionary with CPU health metrics.
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
cpu_usage_percent = psutil.cpu_percent(interval=1)
|
|
|
|
|
cpu_health = {
|
|
|
|
|
'cpu_usage_percent': cpu_usage_percent,
|
2024-12-05 15:30:16 -05:00
|
|
|
'status': 'OK' if cpu_usage_percent < 90 else 'WARNING'
|
2024-12-04 21:55:33 -05:00
|
|
|
}
|
|
|
|
|
return cpu_health
|
2024-12-05 20:18:14 -05:00
|
|
|
|
2024-12-05 15:36:02 -05:00
|
|
|
def _check_network_status(self) -> Dict[str, Any]:
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
2024-12-04 21:55:33 -05:00
|
|
|
Check the status of network interfaces and report any issues.
|
2024-12-05 15:30:16 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
:return: Dictionary containing network health metrics and any issues found.
|
2024-12-04 20:46:35 -05:00
|
|
|
"""
|
|
|
|
|
network_health = {
|
2024-12-04 21:55:33 -05:00
|
|
|
'management_network': {'issues': []},
|
|
|
|
|
'ceph_network': {'issues': []}
|
2024-12-04 20:46:35 -05:00
|
|
|
}
|
2024-12-05 15:30:16 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
try:
|
|
|
|
|
# Check management network connectivity
|
2024-12-05 15:36:02 -05:00
|
|
|
proc = subprocess.run(["ping", "-c", "1", "10.10.10.1"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
2024-12-05 15:30:16 -05:00
|
|
|
if proc.returncode != 0:
|
2024-12-04 21:55:33 -05:00
|
|
|
network_health['management_network']['issues'].append(
|
|
|
|
|
"Management network is unreachable."
|
|
|
|
|
)
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
# Check Ceph network connectivity
|
2024-12-05 15:36:02 -05:00
|
|
|
proc = subprocess.run(["ping", "-c", "1", "10.10.90.1"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
2024-12-05 15:30:16 -05:00
|
|
|
if proc.returncode != 0:
|
2024-12-04 21:55:33 -05:00
|
|
|
network_health['ceph_network']['issues'].append(
|
|
|
|
|
"Ceph network is unreachable."
|
|
|
|
|
)
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-04 21:55:33 -05:00
|
|
|
return network_health
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Network health check failed: {e}")
|
|
|
|
|
return {'error': str(e)}
|
2024-12-04 20:46:35 -05:00
|
|
|
|
2024-12-05 15:30:16 -05:00
|
|
|
def main():
|
|
|
|
|
try:
|
|
|
|
|
# Parse command-line arguments or read from configuration file
|
|
|
|
|
ticket_api_url = "http://10.10.10.45/create_ticket_api.php"
|
|
|
|
|
state_file = "/tmp/last_health_check.json"
|
|
|
|
|
|
|
|
|
|
# Instantiate the SystemHealthMonitor class
|
|
|
|
|
monitor = SystemHealthMonitor(ticket_api_url=ticket_api_url, state_file=state_file)
|
|
|
|
|
|
|
|
|
|
# Run the health checks
|
|
|
|
|
monitor.run()
|
|
|
|
|
|
2024-12-05 15:36:02 -05:00
|
|
|
# Check network health asynchronously
|
|
|
|
|
network_health = asyncio.run(monitor._check_network_status())
|
|
|
|
|
print(f"Network health: {network_health}")
|
|
|
|
|
|
2024-12-05 15:30:16 -05:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
# Handle KeyboardInterrupt gracefully
|
|
|
|
|
print("Interrupted by user. Exiting...")
|
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
# Handle other exceptions
|
|
|
|
|
print(f"An unexpected error occurred: {e}")
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|