фикс фикса
This commit is contained in:
parent
54c851ce8d
commit
a774b613c7
3 changed files with 95 additions and 20 deletions
|
|
@ -27,12 +27,9 @@ async def autodetect_db_from_server(
|
||||||
"""
|
"""
|
||||||
from configparser import RawConfigParser
|
from configparser import RawConfigParser
|
||||||
|
|
||||||
try:
|
config_text = await _read_server_config_with_retry(
|
||||||
config_text = await ssh_run_multi(
|
server_ip, ssh_port, ssh_options, server_config_path
|
||||||
server_ip, ssh_port, ssh_options, f"cat {server_config_path}"
|
)
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
parser = RawConfigParser(strict=False)
|
parser = RawConfigParser(strict=False)
|
||||||
parser.read_string(config_text)
|
parser.read_string(config_text)
|
||||||
|
|
@ -52,6 +49,34 @@ async def autodetect_db_from_server(
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def _read_server_config_with_retry(
|
||||||
|
server_ip: str,
|
||||||
|
ssh_port: int,
|
||||||
|
ssh_options: list,
|
||||||
|
server_config_path: str,
|
||||||
|
attempts: int = 2,
|
||||||
|
) -> str:
|
||||||
|
"""Read server config, retrying once for transient command timeouts."""
|
||||||
|
last_exc: Exception | None = None
|
||||||
|
for attempt in range(1, attempts + 1):
|
||||||
|
try:
|
||||||
|
return await ssh_run_multi(
|
||||||
|
server_ip, ssh_port, ssh_options, f"cat {server_config_path}", timeout=30
|
||||||
|
)
|
||||||
|
except TimeoutError as exc:
|
||||||
|
last_exc = exc
|
||||||
|
if attempt < attempts:
|
||||||
|
logger.warning(
|
||||||
|
"[discovery] Reading server config from %s timed out; retrying (%d/%d)",
|
||||||
|
server_ip, attempt + 1, attempts,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
raise
|
||||||
|
raise last_exc or RuntimeError("server config read failed")
|
||||||
|
|
||||||
|
|
||||||
async def get_rack_hosts(
|
async def get_rack_hosts(
|
||||||
host: str,
|
host: str,
|
||||||
port: int,
|
port: int,
|
||||||
|
|
|
||||||
|
|
@ -257,9 +257,16 @@ async def _resolve_db_connection(
|
||||||
return None
|
return None
|
||||||
elif obj.server_ip:
|
elif obj.server_ip:
|
||||||
await _emit("disc_action", {"message": f"Чтение конфигурации сервера {obj.server_ip}..."})
|
await _emit("disc_action", {"message": f"Чтение конфигурации сервера {obj.server_ip}..."})
|
||||||
detected = await autodetect_db_from_server(
|
try:
|
||||||
server_ip=obj.server_ip, ssh_port=ssh_port, ssh_options=ssh_options,
|
detected = await autodetect_db_from_server(
|
||||||
)
|
server_ip=obj.server_ip, ssh_port=ssh_port, ssh_options=ssh_options,
|
||||||
|
)
|
||||||
|
except Exception as exc:
|
||||||
|
result.errors.append(
|
||||||
|
f"Could not read server config for auto-detection: {exc}. "
|
||||||
|
f"Fill in DB fields manually on the object."
|
||||||
|
)
|
||||||
|
return None
|
||||||
if not detected or not all([detected.get("host"), detected.get("user"), detected.get("dbname")]):
|
if not detected or not all([detected.get("host"), detected.get("user"), detected.get("dbname")]):
|
||||||
await _emit_db_autodetect_error(obj, ssh_port, ssh_options, result)
|
await _emit_db_autodetect_error(obj, ssh_port, ssh_options, result)
|
||||||
return None
|
return None
|
||||||
|
|
@ -283,13 +290,25 @@ async def _resolve_db_connection(
|
||||||
|
|
||||||
async def _emit_db_autodetect_error(obj, ssh_port, ssh_options, result: DiscoveryResult) -> None:
|
async def _emit_db_autodetect_error(obj, ssh_port, ssh_options, result: DiscoveryResult) -> None:
|
||||||
try:
|
try:
|
||||||
raw = await ssh_run_multi(obj.server_ip, ssh_port, ssh_options, "cat /etc/caps/config.ini")
|
raw = await ssh_run_multi(
|
||||||
|
obj.server_ip, ssh_port, ssh_options, "cat /etc/caps/config.ini", timeout=30
|
||||||
|
)
|
||||||
diag_parser = RawConfigParser(strict=False)
|
diag_parser = RawConfigParser(strict=False)
|
||||||
diag_parser.read_string(raw)
|
diag_parser.read_string(raw)
|
||||||
found_sections = diag_parser.sections()
|
found_sections = diag_parser.sections()
|
||||||
found_keys = {s: list(diag_parser.options(s)) for s in found_sections}
|
found_keys = {s: list(diag_parser.options(s)) for s in found_sections}
|
||||||
|
found_db_uri_sections = [
|
||||||
|
s for s in found_sections
|
||||||
|
if diag_parser.get(s, "db_uri", fallback=None)
|
||||||
|
]
|
||||||
|
db_uri_note = (
|
||||||
|
f" db_uri keys were found in sections {found_db_uri_sections}, "
|
||||||
|
f"but none could be parsed as a PostgreSQL URI."
|
||||||
|
if found_db_uri_sections else ""
|
||||||
|
)
|
||||||
result.errors.append(
|
result.errors.append(
|
||||||
f"db_uri not found in server config. "
|
f"db_uri not found in server config. "
|
||||||
|
f"{db_uri_note}"
|
||||||
f"Sections found: {found_sections}. "
|
f"Sections found: {found_sections}. "
|
||||||
f"Keys per section: {found_keys}. "
|
f"Keys per section: {found_keys}. "
|
||||||
f"Fill in DB fields manually on the object."
|
f"Fill in DB fields manually on the object."
|
||||||
|
|
@ -468,12 +487,31 @@ async def _ssh_fetch_rack_config(
|
||||||
Returns (ssh_ok, config_text).
|
Returns (ssh_ok, config_text).
|
||||||
"""
|
"""
|
||||||
await _emit("disc_action", {"message": f"SSH → {rack_host} ({rack_name})"})
|
await _emit("disc_action", {"message": f"SSH → {rack_host} ({rack_name})"})
|
||||||
try:
|
last_exc: Exception | None = None
|
||||||
config_text = await ssh_run_multi(rack_host, ssh_port, ssh_options, f"cat {config_path}")
|
for attempt in range(1, 3):
|
||||||
return True, config_text
|
try:
|
||||||
except Exception as exc:
|
config_text = await ssh_run_multi(
|
||||||
result.errors.append(f"SSH to {rack_host} failed: {exc}")
|
rack_host, ssh_port, ssh_options, f"cat {config_path}", timeout=30
|
||||||
return False, None
|
)
|
||||||
|
return True, config_text
|
||||||
|
except TimeoutError as exc:
|
||||||
|
last_exc = exc
|
||||||
|
if attempt < 2:
|
||||||
|
logger.warning(
|
||||||
|
"[discovery] Reading rack config from %s timed out; retrying (%d/2)",
|
||||||
|
rack_host, attempt + 1,
|
||||||
|
)
|
||||||
|
await _emit("disc_action", {
|
||||||
|
"message": f"Повторное чтение конфигурации {rack_host} ({rack_name})..."
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
except Exception as exc:
|
||||||
|
last_exc = exc
|
||||||
|
break
|
||||||
|
|
||||||
|
result.errors.append(f"SSH to {rack_host} failed: {last_exc}")
|
||||||
|
return False, None
|
||||||
|
|
||||||
|
|
||||||
async def _upsert_rack_device(
|
async def _upsert_rack_device(
|
||||||
|
|
|
||||||
|
|
@ -141,10 +141,22 @@ async def fetch_slave_config(
|
||||||
host: str, port: int, options: list, config_path: str,
|
host: str, port: int, options: list, config_path: str,
|
||||||
) -> str | None:
|
) -> str | None:
|
||||||
"""Read a remote config file from a slave candidate. Returns None on failure."""
|
"""Read a remote config file from a slave candidate. Returns None on failure."""
|
||||||
try:
|
for attempt in range(1, 3):
|
||||||
return await ssh_run_multi(host, port, options, f"cat {config_path}", timeout=15)
|
try:
|
||||||
except Exception:
|
return await ssh_run_multi(host, port, options, f"cat {config_path}", timeout=30)
|
||||||
return None
|
except TimeoutError as exc:
|
||||||
|
if attempt < 2:
|
||||||
|
logger.warning(
|
||||||
|
"[discovery] Reading slave config from %s timed out; retrying (%d/2)",
|
||||||
|
host, attempt + 1,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
logger.warning("[discovery] Reading slave config from %s failed: %s", host, exc)
|
||||||
|
return None
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning("[discovery] Reading slave config from %s failed: %s", host, exc)
|
||||||
|
return None
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def discover_proxmox_via_port_scan(
|
async def discover_proxmox_via_port_scan(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue