feat(ogagent): select network interface by routing table instead of first found
ogagent/pipeline/head This commit looks good
Details
ogagent/pipeline/head This commit looks good
Details
On machines with multiple NICs, the agent was always registering with ogcore using the first interface returned by the OS, which could be the wrong one if it wasn't the interface with a route to ogcore. _best_interface() opens a no-op UDP socket toward the ogcore host and reads the local IP assigned by the kernel routing table, then matches it against the available interfaces. If the routing query fails (network not ready yet) it returns None so the detection loop keeps retrying rather than accepting a wrong interface. Falls back to nets[0] only when the query succeeds but no interface matches (NAT/VPN scenario).pull/76/head
parent
a222528d00
commit
25fc2cf5f8
|
|
@ -34,6 +34,7 @@ import base64
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import shutil
|
import shutil
|
||||||
|
import socket
|
||||||
import string
|
import string
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
|
@ -142,6 +143,36 @@ class OpenGnSysWorker(ServerWorker):
|
||||||
logger.info('Connection to ogcore restored, re-registering')
|
logger.info('Connection to ogcore restored, re-registering')
|
||||||
self._send_started()
|
self._send_started()
|
||||||
|
|
||||||
|
def _best_interface(self, nets):
|
||||||
|
"""
|
||||||
|
Return the interface whose IP the OS routing table would use to reach
|
||||||
|
ogcore, by opening a no-op UDP socket (no packets sent) and reading
|
||||||
|
the local address assigned by the kernel.
|
||||||
|
|
||||||
|
Returns None if the routing query itself fails (network not ready yet),
|
||||||
|
so the caller keeps retrying. Falls back to nets[0] only when the query
|
||||||
|
succeeds but no interface matches the routing IP (e.g. NAT or VPN).
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
host = urllib.parse.urlparse(self.REST.endpoint).hostname
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
|
||||||
|
s.connect((host, 80))
|
||||||
|
local_ip = s.getsockname()[0]
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug('Routing query to ogcore failed (network not ready?): {}'.format(e))
|
||||||
|
return None
|
||||||
|
|
||||||
|
for iface in nets:
|
||||||
|
if iface.ip == local_ip:
|
||||||
|
logger.debug('Selected interface {} ({}) for ogcore at {}'.format(
|
||||||
|
iface.name, local_ip, host))
|
||||||
|
return iface
|
||||||
|
|
||||||
|
# Routing succeeded but no interface matched (NAT/VPN): best effort
|
||||||
|
logger.debug('No interface matched routing IP {}, falling back to {}'.format(
|
||||||
|
local_ip, nets[0].ip))
|
||||||
|
return nets[0]
|
||||||
|
|
||||||
def _setup_network(self, ca_file, crt_file, key_file):
|
def _setup_network(self, ca_file, crt_file, key_file):
|
||||||
"""
|
"""
|
||||||
Background thread: waits indefinitely for a network interface, then
|
Background thread: waits indefinitely for a network interface, then
|
||||||
|
|
@ -159,8 +190,8 @@ class OpenGnSysWorker(ServerWorker):
|
||||||
try:
|
try:
|
||||||
nets = list(operations.getNetworkInfo())
|
nets = list(operations.getNetworkInfo())
|
||||||
if nets:
|
if nets:
|
||||||
self.interface = nets[0]
|
self.interface = self._best_interface(nets)
|
||||||
if t > 0:
|
if self.interface and t > 0:
|
||||||
logger.debug("Network interface found after {} seconds".format(t))
|
logger.debug("Network interface found after {} seconds".format(t))
|
||||||
else:
|
else:
|
||||||
logger.error('No network interfaces found')
|
logger.error('No network interfaces found')
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue