fix: distinguish TLS faults and require active dispatcher retry

This commit is contained in:
2026-10-09 02:24:28 +08:00
parent ba53ad308f
commit 4b27ef31ca
7 changed files with 76 additions and 6 deletions
+18 -3
View File
@@ -119,8 +119,11 @@ def require_reset(requested, confirmed, channels):
def dependency_state(report):
if report.get('success'):
return 'verified'
if report.get('phase') in ('sip', 'providers', 'tasks', 'task_and_quota') and report.get('http_status', 0) in (0, 404, 502, 503, 504):
return 'saas_pending'
if report.get('phase') in ('sip', 'providers', 'tasks', 'task_and_quota'):
if report.get('http_status') in (404, 502, 503, 504):
return 'saas_pending'
if report.get('http_status') == 0 and report.get('transport_failure') == 'unavailable':
return 'saas_pending'
if report.get('phase', '').startswith('mq_'):
return 'mq_failed'
return 'dependency_failed'
@@ -338,6 +341,10 @@ def retire(p, payload):
shutil.copy2(fragment, unit_backup / fragment.name)
(unit_backup / fragment.name).chmod(0o600)
fragment.unlink()
dropin = p['units'] / (unit + '.d')
if dropin.exists():
backup_dir(p, dropin, 'legacy-dropins')
shutil.rmtree(dropin)
run(['systemctl', '--user', 'daemon-reload'])
evidence = {'ok': True, 'legacy_units_removed': len(units), 'legacy_binaries_removed': len(obsolete_binaries), 'legacy_directories_archived': len(archived), 'archive_hashes': archived, 'mock_broker_removed': local_mq, 'active_channels': 0, 'external_services_modified': False}
write_private(p['backups'] / 'retirement.json', json.dumps(evidence, indent=2))
@@ -424,6 +431,14 @@ def install(payload, p):
return result
def dispatcher_acceptable(dispatcher, waiting_reason):
if dispatcher.get('UnitFileState') != 'enabled':
return False
if dispatcher.get('ActiveState') == 'active':
return True
return bool(waiting_reason) and dispatcher.get('ActiveState') == 'activating' and dispatcher.get('SubState') == 'auto-restart'
def status(p):
units = {u: {k: v for k, v in unit_properties(u).items() if k in ('ActiveState', 'SubState', 'UnitFileState', 'ExecMainStatus')} for u in UNITS}
manifest = p['current'] / 'manifest.json'
@@ -450,7 +465,7 @@ def status(p):
waiting_reason = 'saas_topology_pending'
elif '/internal/v1/dispatcher/' in logs and any(v in logs.lower() for v in ('timeout', 'connection refused', 'no such host')):
waiting_reason = 'saas_network_unavailable'
acceptable = dispatcher['UnitFileState'] == 'enabled' and (dispatcher['ActiveState'] == 'active' or (waiting_reason is not None and dispatcher['ActiveState'] in ('activating', 'failed')))
acceptable = dispatcher_acceptable(dispatcher, waiting_reason)
return {'ok': healthy and acceptable, 'services': units, 'artifact_hashes_match': matches, 'agent_listener': listen, 'active_channels': len(ari(p['home'])), 'dependency_state': dependency, 'business_ready': dependency == 'verified' and dispatcher['ActiveState'] == 'active', 'commit': release['commit'] if release else None, 'waiting_reason': waiting_reason, 'real_reboot_verified': False}