realm:wait_for_ip: re-write logic for correctness and debugging.

Check ipv6 and ipv4 independently of each other.

Auto-timeout check is moved to top of the method.

Improve debugging output.

Fix logic that attempted to print out all ports when
there is failure to find IPs for at least one of the ports.

Signed-off-by: Ben Greear <greearb@candelatech.com>
This commit is contained in:
Ben Greear
2021-12-29 11:36:15 -08:00
committed by shivam
parent a8bd985119
commit 8446d8fc1b

View File

@@ -615,15 +615,24 @@ class Realm(LFCliBase):
def dump_all_port_info(self): def dump_all_port_info(self):
return self.json_get('/port/all') return self.json_get('/port/all')
# timemout_sec of -1 means auto-calculate based on number of stations.
def wait_for_ip(self, station_list=None, ipv4=True, ipv6=False, timeout_sec=360, debug=False): def wait_for_ip(self, station_list=None, ipv4=True, ipv6=False, timeout_sec=360, debug=False):
timeout_auto = False
if not (ipv4 or ipv6): if not (ipv4 or ipv6):
raise ValueError("wait_for_ip: ipv4 and/or ipv6 must be set!") raise ValueError("wait_for_ip: ipv4 and/or ipv6 must be set!")
if timeout_sec >= 0: if timeout_sec >= 0:
print("Waiting for ips, timeout: %i..." % timeout_sec) if debug:
print("Waiting for ips, timeout: %i..." % timeout_sec)
else: else:
print("Determining wait time based on mean station association time of stations. " timeout_auto = True
"Will not wait more that 60 seconds without single association") timeout_sec = 60 + len(station_list) * 5
stas_with_ips = {} if debug:
print("Auto-Timeout requested, using: %s" % timeout_sec)
stas_without_ip4s = {}
stas_without_ip6s = {}
sec_elapsed = 0 sec_elapsed = 0
time_extended = False time_extended = False
# print(station_list) # print(station_list)
@@ -632,24 +641,13 @@ class Realm(LFCliBase):
raise ValueError("wait_for_ip: expects non-empty list of ports") raise ValueError("wait_for_ip: expects non-empty list of ports")
wait_more = True wait_more = True
while wait_more and (sec_elapsed <= timeout_sec or timeout_sec == -1): while wait_more and (sec_elapsed <= timeout_sec):
wait_more = False wait_more = False
some_passed = False
if not time_extended and timeout_sec == -1: stas_without_ip4s = {}
wait_more = True stas_without_ip6s = {}
num_with_ips = len(stas_with_ips)
if sec_elapsed >= 10 and num_with_ips > 0:
time_extended = True
# print(sec_elapsed, num_with_ips, int(sec_elapsed / num_with_ips), len(station_list))
timeout_sec = int(sec_elapsed / num_with_ips * len(station_list))
print("New timeout is %d seconds" % timeout_sec)
elif sec_elapsed > 60 and num_with_ips == 0:
timeout_sec = 60
wait_more = False
for sta_eid in station_list: for sta_eid in station_list:
if debug:
print("checking sta-eid: %s" % sta_eid)
eid = self.name_to_eid(sta_eid) eid = self.name_to_eid(sta_eid)
response = super().json_get("/port/%s/%s/%s?fields=alias,ip,port+type,ipv6+address" % response = super().json_get("/port/%s/%s/%s?fields=alias,ip,port+type,ipv6+address" %
@@ -657,7 +655,7 @@ class Realm(LFCliBase):
# pprint(response) # pprint(response)
if (response is None) or ("interface" not in response): if (response is None) or ("interface" not in response):
print("station_list: incomplete response:") print("station_list: incomplete response for eid: %s:" % sta_eid)
pprint(response) pprint(response)
wait_more = True wait_more = True
break break
@@ -666,69 +664,51 @@ class Realm(LFCliBase):
v = response['interface'] v = response['interface']
if v['ip'] in waiting_states: if v['ip'] in waiting_states:
wait_more = True wait_more = True
stas_without_ip4s[sta_eid] = True
if debug: if debug:
print("Waiting for port %s to get IPv4 Address." % sta_eid) print("Waiting for port %s to get IPv4 Address try %s / %s" % (sta_eid, sec_elapsed, timeout_sec))
else: else:
if sta_eid not in stas_with_ips: some_passed = True
stas_with_ips[sta_eid] = {'ipv4': v['ip']}
else:
stas_with_ips[sta_eid]['ipv4'] = v['ip']
if debug: if debug:
print("Found IP: %s on port: %s" % (v['ip'], sta_eid)) print("Found IP: %s on port: %s" % (v['ip'], sta_eid))
if ipv6: if ipv6:
v = response['interface'] v = response['interface']
# print(v) # print(v)
if v['ipv6 address'] != 'DELETED' and not v['ipv6 address'].startswith('fe80') \ ip6a = v['ipv6_address']
and v['ipv6 address'] != 'AUTO': if ip6a != 'DELETED' and not ip6a.startswith('fe80') and ip6a != 'AUTO':
if sta_eid not in stas_with_ips: some_passed = True
stas_with_ips[sta_eid] = {'ipv6': v['ip']}
else:
stas_with_ips[sta_eid]['ipv6'] = v['ip']
if debug: if debug:
print("Found IPv6: %s on port: %s" % (v['ipv6 address'], sta_eid)) print("Found IPv6: %s on port: %s" % (ip6a, sta_eid))
else: else:
stas_without_ip6s[sta_eid] = True
wait_more = True wait_more = True
if debug: if debug:
print("Waiting for port %s to get IPv6 Address." % sta_eid) print("Waiting for port %s to get IPv6 Address try %s / %s, reported: %s." % (sta_eid, sec_elapsed, timeout_sec, ip6a))
if wait_more: if wait_more:
if timeout_auto and not some_passed:
if sec_elapsed > 60:
# Nothing has gotten IP for 60 seconds, consider timeout reached.
break
time.sleep(1) time.sleep(1)
sec_elapsed += 1 sec_elapsed += 1
port_info = self.dump_all_port_info() # If not all ports got IP addresses before timeout, and debugging is enabled, then
ports_of_interest = list() # ports_of_interest = [item for item in port_info['interfaces'] if list(item.keys())[0] in station_list] # add logging.
for item in port_info['interfaces']: if len(stas_without_ip4s) + len(stas_without_ip6s) > 0:
if list(item.keys())[0] in station_list: if debug:
ports_of_interest.append(item) if len(stas_without_ip4s) > 0:
port_names = list() # port_names = [list(port.keys())[0] for port in ports_of_interest] print('%s did not acquire IPv4 addresses' % stas_without_ip4s.keys())
ipv4_addresses = list() # ipv4_addresses = [list(port.values())[0]['ip'] for port in ports_of_interest] if len(stas_without_ip6s) > 0:
ipv6_addresses = list() # ipv6_addresses = [list(port.values())[0]['ipv6 address'] for port in ports_of_interest] print('%s did not acquire IPv6 addresses' % stas_without_ip6s.keys())
for port in ports_of_interest: port_info = self.dump_all_port_info()
port_names.append(list(port.keys())[0]) pprint(self.dump_all_port_info())
ipv4_addresses.append(list(port.values())[0]['ip']) return False
ipv6_addresses.append(list(port.values())[0]['ipv6 address']) else:
if debug:
if ipv4: print("Found IPs for all requested ports.")
if len(set(ipv4_addresses) & set(waiting_states)) > 0: return True
targets = dict(zip(port_names, ipv4_addresses))
sta_without_ips = {k: v for k, v in targets.items() if v in waiting_states}
if len(sta_without_ips) > 0:
print('%s did not acquire IP addresses' % sta_without_ips.keys())
if self.debug:
pprint(self.dump_all_port_info())
if ipv6:
fe80_failures = [x.startswith('fe80') for x in ipv6_addresses]
if len(set(ipv6_addresses) & set(waiting_states)) > 0 or len(fe80_failures) > 0:
targets = dict(zip(port_names, ipv6_addresses))
sta_without_ips = {k: v for k, v in targets.items() if v in waiting_states}.keys()
sta_without_ips = list(sta_without_ips) + fe80_failures
if len(sta_without_ips) > 0:
print('%s did not acquire IPv6 addresses' % sta_without_ips)
if self.debug:
pprint(self.dump_all_port_info())
return not wait_more
def get_curr_num_ips(self, num_sta_with_ips=0, station_list=None, ipv4=True, ipv6=False, debug=False): def get_curr_num_ips(self, num_sta_with_ips=0, station_list=None, ipv4=True, ipv6=False, debug=False):
if debug: if debug: