ssh туннель для БД
This commit is contained in:
parent
67f440682f
commit
317b701afe
2 changed files with 63 additions and 7 deletions
|
|
@ -710,11 +710,48 @@ async def discover_via_ssh(
|
|||
)
|
||||
return result
|
||||
|
||||
# Step 0.5: upsert DB server as a device now (before connection attempt),
|
||||
# so the user can see it and configure tunnel even if connection fails.
|
||||
now_pre = datetime.now(timezone.utc)
|
||||
db_device_obj: Device | None = None
|
||||
if db_host and db_host != obj.server_ip:
|
||||
try:
|
||||
db_device_obj = (await db.execute(
|
||||
select(Device).where(Device.object_id == obj.id, Device.ip == db_host)
|
||||
)).scalar_one_or_none()
|
||||
if db_device_obj is None:
|
||||
db_device_obj = Device(
|
||||
object_id=obj.id,
|
||||
ip=db_host,
|
||||
hostname="db_server",
|
||||
category="vm",
|
||||
role="other",
|
||||
source="auto_ssh",
|
||||
location="server_room",
|
||||
status="unknown",
|
||||
)
|
||||
db.add(db_device_obj)
|
||||
await db.flush()
|
||||
logger.info("[ssh_discovery] %s (db_server) - PRE-ADDED before connection attempt", db_host)
|
||||
result.created += 1
|
||||
result.actions.append(DeviceAction(
|
||||
ip=db_host, hostname="db_server", action="ADDED",
|
||||
reason="object infrastructure device (vm/db_server)", category="vm", role="other",
|
||||
))
|
||||
except Exception as exc:
|
||||
logger.warning("[ssh_discovery] Failed to pre-upsert db_server device %s: %s", db_host, exc)
|
||||
|
||||
# Read tunnel flag from the device (user may have set it via UI), fall back to object setting
|
||||
device_via_tunnel = bool(
|
||||
(db_device_obj.connection_params or {}).get("db_via_tunnel")
|
||||
) if db_device_obj else False
|
||||
use_tunnel = device_via_tunnel or obj.db_via_tunnel
|
||||
|
||||
# Step 1: get rack hosts from object's DB
|
||||
await _emit("disc_action", {"message": "Получение списка стоек из БД..."})
|
||||
logger.info(
|
||||
"[ssh_discovery] Connecting to object DB: host=%s port=%s dbname=%s user=%s table=%s via_tunnel=%s",
|
||||
db_host, db_port, db_name, db_user, db_table, obj.db_via_tunnel,
|
||||
db_host, db_port, db_name, db_user, db_table, use_tunnel,
|
||||
)
|
||||
try:
|
||||
rack_hosts = await _get_rack_hosts_direct(
|
||||
|
|
@ -724,14 +761,24 @@ async def discover_via_ssh(
|
|||
password=db_password or "",
|
||||
dbname=db_name,
|
||||
table=db_table,
|
||||
via_tunnel=obj.db_via_tunnel,
|
||||
via_tunnel=use_tunnel,
|
||||
tunnel_host=obj.server_ip,
|
||||
tunnel_ssh_port=ssh_port,
|
||||
tunnel_ssh_user=obj.ssh_user,
|
||||
tunnel_ssh_password=ssh_password,
|
||||
)
|
||||
# Connection succeeded — mark DB device online
|
||||
if db_device_obj is not None:
|
||||
db_device_obj.status = "online"
|
||||
db_device_obj.last_seen = now_pre
|
||||
except Exception as exc:
|
||||
result.errors.append(f"Cannot fetch rack hosts from object DB: {exc}")
|
||||
# Mark DB device offline so the user sees it's unreachable
|
||||
if db_device_obj is not None:
|
||||
db_device_obj.status = "offline"
|
||||
err_msg = f"Cannot fetch rack hosts from object DB: {exc}"
|
||||
if "timeout" in str(exc).lower():
|
||||
err_msg += ". Попробуйте настроить SSH-туннель (отредактируйте устройство БД и включите опцию)"
|
||||
result.errors.append(err_msg)
|
||||
return result
|
||||
|
||||
if not rack_hosts:
|
||||
|
|
@ -774,14 +821,12 @@ async def discover_via_ssh(
|
|||
rack_id_mapping[ext_id] = new_rack.id
|
||||
logger.info(f"[ssh_discovery] Created rack entry '{rack_name}' rack_type={rack_type_db} (id={new_rack.id})")
|
||||
|
||||
# Step 1b: Add main CAPS server and DB server as devices
|
||||
# Step 1b: Add main CAPS server as device (DB server was already upserted in Step 0.5)
|
||||
# verified=True means we successfully connected to this host during this discovery run
|
||||
now = datetime.now(timezone.utc)
|
||||
infra_devices = []
|
||||
if obj.server_ip:
|
||||
infra_devices.append((obj.server_ip, "main_server", "caps_server", server_ip_ssh_verified))
|
||||
if db_host and db_host != obj.server_ip:
|
||||
infra_devices.append((db_host, "vm", "db_server", True)) # DB query succeeded = online
|
||||
|
||||
for infra_ip, infra_category, infra_hostname, infra_verified in infra_devices:
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ export function DeviceEditModal({ open, device, objId, onClose, onSaved }: Props
|
|||
ssh_user_override: device.ssh_user_override ?? '',
|
||||
ssh_port_override: device.ssh_port_override ?? undefined,
|
||||
ssh_key_id_override: device.ssh_key_id_override ?? undefined,
|
||||
db_via_tunnel: !!(device.connection_params?.db_via_tunnel),
|
||||
})
|
||||
} else {
|
||||
form.resetFields()
|
||||
|
|
@ -86,10 +87,14 @@ export function DeviceEditModal({ open, device, objId, onClose, onSaved }: Props
|
|||
|
||||
const handleOk = async () => {
|
||||
const values = await form.validateFields()
|
||||
const payload = stripEmpty(values)
|
||||
const { db_via_tunnel, ...rest } = values
|
||||
const payload = stripEmpty(rest)
|
||||
if ('rack_id' in values && values.rack_id === undefined) {
|
||||
payload.rack_id = null
|
||||
}
|
||||
// Merge db_via_tunnel into connection_params
|
||||
const existingParams = device?.connection_params ?? {}
|
||||
payload.connection_params = { ...existingParams, db_via_tunnel: !!db_via_tunnel }
|
||||
try {
|
||||
let saved: DeviceItem
|
||||
if (device) {
|
||||
|
|
@ -213,6 +218,12 @@ export function DeviceEditModal({ open, device, objId, onClose, onSaved }: Props
|
|||
options={(sshKeys ?? []).map((k) => ({ value: k.id, label: `${k.name} (${k.path})` }))}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Divider orientation="left" plain>Подключение к БД</Divider>
|
||||
|
||||
<Form.Item name="db_via_tunnel" valuePropName="checked">
|
||||
<Checkbox>Подключаться к БД через SSH-туннель (через main_server объекта)</Checkbox>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue