DNS fill timeout via thread + tag_obsolete_os supporte els/obsolete separement

This commit is contained in:
Pierre & Lumière 2026-04-14 20:37:46 +02:00
parent 7f6ccc763b
commit 9f4d7707ef
2 changed files with 43 additions and 23 deletions

View File

@ -10,6 +10,7 @@ Usage:
""" """
import os import os
import socket import socket
import threading
import argparse import argparse
from sqlalchemy import create_engine, text from sqlalchemy import create_engine, text
@ -26,13 +27,21 @@ SUFFIXES = [
def resolve(hostname, suffix, timeout): def resolve(hostname, suffix, timeout):
"""Retourne True si hostname.suffix resout en DNS.""" """Retourne True si hostname.suffix resout en DNS, timeout via thread."""
socket.setdefaulttimeout(timeout) fqdn = f"{hostname}.{suffix}"
try: result = [False]
socket.gethostbyname(f"{hostname}.{suffix}")
return True def _do():
except (socket.gaierror, socket.timeout, OSError): try:
return False socket.gethostbyname(fqdn)
result[0] = True
except Exception:
result[0] = False
t = threading.Thread(target=_do, daemon=True)
t.start()
t.join(timeout)
return result[0]
def main(): def main():
@ -53,11 +62,12 @@ def main():
print(f"[INFO] {len(rows)} serveurs sans domain_ltd") print(f"[INFO] {len(rows)} serveurs sans domain_ltd")
updated = skipped = 0 updated = skipped = 0
for r in rows: for i, r in enumerate(rows, 1):
h = (r.hostname or "").strip() h = (r.hostname or "").strip()
if not h: if not h:
skipped += 1 skipped += 1
continue continue
print(f" [{i}/{len(rows)}] Resolve {h}...", flush=True)
found = None found = None
for suffix in SUFFIXES: for suffix in SUFFIXES:
if resolve(h, suffix, args.timeout): if resolve(h, suffix, args.timeout):

View File

@ -23,9 +23,10 @@ from sqlalchemy import create_engine, text
DATABASE_URL = os.getenv("DATABASE_URL_DEMO") or os.getenv("DATABASE_URL") \ DATABASE_URL = os.getenv("DATABASE_URL_DEMO") or os.getenv("DATABASE_URL") \
or "postgresql://patchcenter:PatchCenter2026!@localhost:5432/patchcenter_demo" or "postgresql://patchcenter:PatchCenter2026!@localhost:5432/patchcenter_demo"
# Patterns regex (case-insensitive) sur os_version indiquant un OS EOL # OS deja en EOL complet (licence_support='obsolete')
EOL_PATTERNS = [ EOL_PATTERNS = [
(r"red\s*hat.*(?:release\s+)?[567]\b", "RHEL 5/6/7"), (r"red\s*hat.*(?:release\s+)?[56]\b", "RHEL 5/6"),
(r"red\s*hat.*(?:release\s+)?7\b", "RHEL 7 (EOL 2024-06)"),
(r"centos.*(?:release\s+)?[5678]\b", "CentOS 5/6/7/8"), (r"centos.*(?:release\s+)?[5678]\b", "CentOS 5/6/7/8"),
(r"oracle.*linux.*(?:release\s+)?[567]\b", "Oracle Linux 5/6/7"), (r"oracle.*linux.*(?:release\s+)?[567]\b", "Oracle Linux 5/6/7"),
(r"windows.*2003", "Windows 2003"), (r"windows.*2003", "Windows 2003"),
@ -37,15 +38,24 @@ EOL_PATTERNS = [
(r"suse.*(?:enterprise.*)?(?:server.*)?(?:sp\d\s*)?1[01]\b", "SUSE 10/11"), (r"suse.*(?:enterprise.*)?(?:server.*)?(?:sp\d\s*)?1[01]\b", "SUSE 10/11"),
] ]
# OS avec support etendu (ELS) - licence_support='els'
ELS_PATTERNS = [
# RHEL 7 est en ELS jusqu'en 2028 pour les clients payants
# On peut basculer certains vers ELS au lieu de obsolete au cas par cas
]
def classify(os_version): def classify(os_version):
if not os_version: if not os_version:
return None return (None, None)
v = os_version.lower() v = os_version.lower()
for pattern, label in ELS_PATTERNS:
if re.search(pattern, v):
return ("els", label)
for pattern, label in EOL_PATTERNS: for pattern, label in EOL_PATTERNS:
if re.search(pattern, v): if re.search(pattern, v):
return label return ("obsolete", label)
return None return (None, None)
def main(): def main():
@ -70,28 +80,28 @@ def main():
by_label = {} by_label = {}
for r in rows: for r in rows:
label = classify(r.os_version) target, label = classify(r.os_version)
if not label: if not target:
stats["not_eol"] += 1 stats["not_eol"] += 1
continue continue
if r.licence_support == "obsolete": if r.licence_support == target:
stats["already_obsolete"] += 1 stats["already_obsolete"] += 1
continue continue
# Si deja 'active' ou 'els', on ne touche pas sauf --overwrite # Si deja 'active' et qu'on veut passer en obsolete/els, skip sauf --overwrite
if r.licence_support in ("active", "els") and not args.overwrite: if r.licence_support == "active" and not args.overwrite:
stats["skipped_active"] += 1 stats["skipped_active"] += 1
if args.dry_run: if args.dry_run:
print(f" SKIP (--overwrite pour forcer): {r.hostname:25s} " print(f" SKIP (--overwrite pour forcer): {r.hostname:25s} "
f"[{r.licence_support}] {label} | {r.os_version[:60]}") f"[active] -> {target} ({label}) | {r.os_version[:60]}")
continue continue
by_label[label] = by_label.get(label, 0) + 1 by_label[f"{target} - {label}"] = by_label.get(f"{target} - {label}", 0) + 1
if args.dry_run: if args.dry_run:
print(f" DRY: {r.hostname:25s} [{r.licence_support or 'NULL'}] -> obsolete " print(f" DRY: {r.hostname:25s} [{r.licence_support or 'NULL'}] -> {target} "
f"({label}) | {r.os_version[:60]}") f"({label}) | {r.os_version[:60]}")
else: else:
conn.execute(text("UPDATE servers SET licence_support='obsolete' WHERE id=:sid"), conn.execute(text("UPDATE servers SET licence_support=:t WHERE id=:sid"),
{"sid": r.id}) {"t": target, "sid": r.id})
stats["tagged"] += 1 stats["tagged"] += 1
conn.close() conn.close()