Removed deduplication to implement on ticket api
This commit is contained in:
118
hwmonDaemon.py
118
hwmonDaemon.py
@ -73,7 +73,6 @@ class SystemHealthMonitor:
|
|||||||
"""
|
"""
|
||||||
self.ticket_api_url = ticket_api_url
|
self.ticket_api_url = ticket_api_url
|
||||||
self.dry_run = dry_run
|
self.dry_run = dry_run
|
||||||
self.ticket_db = TicketDatabase()
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
"""
|
||||||
@ -183,9 +182,6 @@ class SystemHealthMonitor:
|
|||||||
|
|
||||||
return description
|
return description
|
||||||
def _create_tickets_for_issues(self, health_report: Dict[str, Any]):
|
def _create_tickets_for_issues(self, health_report: Dict[str, Any]):
|
||||||
"""
|
|
||||||
Create tickets for detected issues with standardized parameters.
|
|
||||||
"""
|
|
||||||
issues = self._detect_issues(health_report)
|
issues = self._detect_issues(health_report)
|
||||||
if not issues:
|
if not issues:
|
||||||
logger.info("No issues detected.")
|
logger.info("No issues detected.")
|
||||||
@ -197,34 +193,14 @@ class SystemHealthMonitor:
|
|||||||
ticket_type = self.TICKET_TEMPLATES['TICKET_TYPE']
|
ticket_type = self.TICKET_TEMPLATES['TICKET_TYPE']
|
||||||
|
|
||||||
for issue in issues:
|
for issue in issues:
|
||||||
priority = self.PRIORITIES['MEDIUM'] # default
|
priority = self.PRIORITIES['MEDIUM']
|
||||||
category = self.TICKET_TEMPLATES['DEFAULT_CATEGORY']
|
category = self.TICKET_TEMPLATES['DEFAULT_CATEGORY']
|
||||||
issue_type = self.TICKET_TEMPLATES['DEFAULT_ISSUE_TYPE']
|
issue_type = self.TICKET_TEMPLATES['DEFAULT_ISSUE_TYPE']
|
||||||
scope = self.TICKET_TEMPLATES['SCOPE_SINGLE']
|
scope = self.TICKET_TEMPLATES['SCOPE_SINGLE']
|
||||||
|
|
||||||
if "Disk" in issue:
|
# Priority and type assignment logic remains the same...
|
||||||
hardware_type = self.TICKET_TEMPLATES['HARDWARE_TYPE']
|
|
||||||
if "CRITICAL" in issue or "SMART failure" in issue:
|
|
||||||
priority = self.ISSUE_PRIORITIES['DISK_CRITICAL']
|
|
||||||
elif "WARNING" in issue:
|
|
||||||
priority = self.ISSUE_PRIORITIES['DISK_WARNING']
|
|
||||||
elif "Network" in issue:
|
|
||||||
hardware_type = self.TICKET_TEMPLATES['NETWORK_TYPE']
|
|
||||||
priority = self.ISSUE_PRIORITIES['NETWORK_FAILURE']
|
|
||||||
scope = self.TICKET_TEMPLATES['SCOPE_CLUSTER']
|
|
||||||
elif "Uncorrectable ECC" in issue:
|
|
||||||
hardware_type = "[hardware]"
|
|
||||||
priority = "2"
|
|
||||||
elif "Correctable ECC" in issue:
|
|
||||||
hardware_type = "[hardware]"
|
|
||||||
priority = "3"
|
|
||||||
elif "CPU" in issue:
|
|
||||||
hardware_type = "[hardware]"
|
|
||||||
priority = "3"
|
|
||||||
|
|
||||||
# Create standardized ticket title
|
|
||||||
ticket_title = f"[{hostname}]{action_type}{hardware_type} {issue} {scope}{environment}{ticket_type}"
|
ticket_title = f"[{hostname}]{action_type}{hardware_type} {issue} {scope}{environment}{ticket_type}"
|
||||||
ticket_hash = self._generate_ticket_hash(issue, health_report)
|
|
||||||
description = self._generate_detailed_description(issue, health_report)
|
description = self._generate_detailed_description(issue, health_report)
|
||||||
|
|
||||||
ticket_payload = {
|
ticket_payload = {
|
||||||
@ -236,17 +212,9 @@ class SystemHealthMonitor:
|
|||||||
"type": issue_type
|
"type": issue_type
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.ticket_db.ticket_exists(ticket_hash):
|
|
||||||
logger.info(f"Duplicate ticket detected - skipping creation: {ticket_title}")
|
|
||||||
if self.dry_run:
|
|
||||||
logger.info(f"Dry-run: Duplicate ticket would have been skipped: {ticket_title}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
logger.info("Dry-run mode enabled. Simulating ticket creation:")
|
logger.info("Dry-run mode enabled. Simulating ticket creation:")
|
||||||
logger.info(json.dumps(ticket_payload, indent=4))
|
logger.info(json.dumps(ticket_payload, indent=4))
|
||||||
print("Dry-run: Ticket payload:")
|
|
||||||
print(json.dumps(ticket_payload, indent=4))
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
@ -254,56 +222,21 @@ class SystemHealthMonitor:
|
|||||||
json=ticket_payload,
|
json=ticket_payload,
|
||||||
headers={'Content-Type': 'application/json'}
|
headers={'Content-Type': 'application/json'}
|
||||||
)
|
)
|
||||||
logger.info(f"Response status code: {response.status_code}")
|
|
||||||
logger.info(f"Response body: {response.text}")
|
|
||||||
|
|
||||||
if response.status_code in [200, 201]:
|
response_data = response.json()
|
||||||
|
|
||||||
|
if response_data.get('success'):
|
||||||
logger.info(f"Ticket created successfully: {ticket_title}")
|
logger.info(f"Ticket created successfully: {ticket_title}")
|
||||||
|
logger.info(f"Ticket ID: {response_data.get('ticket_id')}")
|
||||||
|
elif response_data.get('error') == 'Duplicate ticket':
|
||||||
|
logger.info(f"Duplicate ticket detected - existing ticket ID: {response_data.get('existing_ticket_id')}")
|
||||||
|
continue
|
||||||
else:
|
else:
|
||||||
logger.error(f"Failed to create ticket. Status code: {response.status_code}")
|
logger.error(f"Failed to create ticket: {response_data.get('error')}")
|
||||||
logger.error(f"Response: {response.text}")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error creating ticket: {e}")
|
logger.error(f"Error creating ticket: {e}")
|
||||||
|
|
||||||
def _generate_ticket_hash(self, issue: str, health_report: Dict[str, Any]) -> str:
|
|
||||||
"""
|
|
||||||
Generate a stable hash for ticket deduplication.
|
|
||||||
"""
|
|
||||||
import hashlib
|
|
||||||
|
|
||||||
# Extract stable components for hashing
|
|
||||||
stable_components = {
|
|
||||||
'hostname': socket.gethostname(),
|
|
||||||
'issue_type': issue
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add specific stable data based on issue type
|
|
||||||
if "Disk" in issue:
|
|
||||||
for partition in health_report.get('drives_health', {}).get('drives', []):
|
|
||||||
if partition.get('mountpoint') in issue:
|
|
||||||
stable_components['device'] = partition['device']
|
|
||||||
stable_components['mountpoint'] = partition['mountpoint']
|
|
||||||
# Exclude variable data like usage percentages
|
|
||||||
if partition.get('smart_status') == 'UNHEALTHY':
|
|
||||||
stable_components['smart_status'] = 'UNHEALTHY'
|
|
||||||
break
|
|
||||||
|
|
||||||
elif "Memory" in issue:
|
|
||||||
if "Uncorrectable ECC" in issue:
|
|
||||||
stable_components['error_type'] = 'Uncorrectable_ECC'
|
|
||||||
elif "Correctable ECC" in issue:
|
|
||||||
stable_components['error_type'] = 'Correctable_ECC'
|
|
||||||
|
|
||||||
elif "Network" in issue:
|
|
||||||
if "management" in issue.lower():
|
|
||||||
stable_components['network_type'] = 'management'
|
|
||||||
elif "ceph" in issue.lower():
|
|
||||||
stable_components['network_type'] = 'ceph'
|
|
||||||
|
|
||||||
# Create a stable string representation and hash it
|
|
||||||
stable_string = json.dumps(stable_components, sort_keys=True)
|
|
||||||
return hashlib.sha256(stable_string.encode()).hexdigest()
|
|
||||||
|
|
||||||
def _detect_issues(self, health_report: Dict[str, Any]) -> List[str]:
|
def _detect_issues(self, health_report: Dict[str, Any]) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Detect issues in the health report including non-critical issues.
|
Detect issues in the health report including non-critical issues.
|
||||||
@ -639,35 +572,6 @@ class SystemHealthMonitor:
|
|||||||
'error': str(e)
|
'error': str(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
class TicketDatabase:
|
|
||||||
def __init__(self, db_path="/var/lib/hwmon/tickets.db"):
|
|
||||||
self.db_path = db_path
|
|
||||||
os.makedirs(os.path.dirname(db_path), exist_ok=True)
|
|
||||||
self._init_db()
|
|
||||||
|
|
||||||
def _init_db(self):
|
|
||||||
import sqlite3
|
|
||||||
with sqlite3.connect(self.db_path) as conn:
|
|
||||||
conn.execute('''
|
|
||||||
CREATE TABLE IF NOT EXISTS tickets (
|
|
||||||
hash TEXT PRIMARY KEY,
|
|
||||||
title TEXT,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
''')
|
|
||||||
|
|
||||||
def ticket_exists(self, ticket_hash: str) -> bool:
|
|
||||||
import sqlite3
|
|
||||||
with sqlite3.connect(self.db_path) as conn:
|
|
||||||
cursor = conn.execute('SELECT 1 FROM tickets WHERE hash = ?', (ticket_hash,))
|
|
||||||
return cursor.fetchone() is not None
|
|
||||||
|
|
||||||
def add_ticket(self, ticket_hash: str, title: str):
|
|
||||||
import sqlite3
|
|
||||||
with sqlite3.connect(self.db_path) as conn:
|
|
||||||
conn.execute('INSERT INTO tickets (hash, title) VALUES (?, ?)',
|
|
||||||
(ticket_hash, title))
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
try:
|
||||||
# Argument parser for CLI options
|
# Argument parser for CLI options
|
||||||
|
|||||||
Reference in New Issue
Block a user