fix(deploy): recover control core migration replay

This commit is contained in:
Codex
2026-08-22 21:12:27 +03:00
parent bd715e9d71
commit e642113124
+639 -4
View File
@@ -450,6 +450,67 @@ DEVICE_PLANE_CONTROL_CORE_INCIDENT_AUDIT_ENTRIES = (
DEVICE_PLANE_CONTROL_CORE_INCIDENT_AUDIT_PATCH_ID = (
"device-control-core-incident-audit-20260822-043"
)
DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_REL = (
"deployment/device-control-core-migration-replay-recovery-v1.json"
)
DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_REL = (
"services/device-control-core/migrations/"
"014_device_registry_profile_commands.sql"
)
DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_ENTRIES = (
DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_REL,
DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_REL,
)
DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_PATCH_ID = (
"device-control-core-migration-replay-recovery-20260822-044"
)
DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_PREDECESSOR_SHA256 = (
"751accf346b34d2774cc7b9572640d2c25fdb0b1db793ac32183b56f48e26508"
)
DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_TARGET_SHA256 = (
"38bd86b42828d44c7101d5433ddc36018e92eedeee37b9de296432ad676edd46"
)
DEVICE_PLANE_CONTROL_CORE_FINAL_COMMAND_KINDS = (
"owner_scope.ensure",
"project.ensure",
"collection.ensure",
"project_grant.upsert",
"adapter_package.ensure",
"adapter_version.register",
"model_profile.register",
"edge.ensure",
"route.ensure",
"enrollment_intent.ensure",
"device.claim",
"device.update",
"device.transfer",
"discovery.reject",
"discovery.expire",
"device_credential_binding.upsert",
"device_credential_binding.revoke",
"device_binding.ensure",
"device_binding.revoke",
"device_configuration_revision.create",
"device_configuration_desired.set",
"asset.ensure",
"asset_binding.ensure",
"asset_binding.close",
"infrastructure_host.ensure",
"infrastructure_endpoint.ensure",
"infrastructure_deployment.ensure",
"infrastructure_service_instance.ensure",
"health_observation.record",
)
DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_TRIGGER_KINDS = (
"asset.ensure",
"asset_binding.ensure",
"asset_binding.close",
"infrastructure_host.ensure",
"infrastructure_endpoint.ensure",
"infrastructure_deployment.ensure",
"infrastructure_service_instance.ensure",
"health_observation.record",
)
DEVICE_PLANE_CONTROL_CORE_V3_RECONCILIATION_FAILED_ARTIFACT = (
"nodedc-device-plane-device-control-core-release-v3-reconciliation-"
"20260822-042.tgz.20260822-195448"
@@ -4813,6 +4874,7 @@ def allowed_payload_path(component, rel):
DEVICE_PLANE_CONTROL_CORE_RELEASE_V3_REL,
DEVICE_PLANE_CONTROL_CORE_V3_RECONCILIATION_REL,
DEVICE_PLANE_CONTROL_CORE_INCIDENT_AUDIT_REL,
DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_REL,
DEVICE_PLANE_MANAGER_RECONCILIATION_REL,
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_REL,
"packages/device-protocol-contract",
@@ -11274,6 +11336,23 @@ def load_artifact(artifact, work_dir):
validate_device_plane_control_core_v3_reconciliation_payload(
payload_dir
)
if is_device_plane_control_core_incident_audit_slice(
manifest["component"],
entries,
):
validate_device_plane_control_core_incident_audit_payload(payload_dir)
if is_device_plane_control_core_migration_replay_recovery_slice(
manifest["component"],
entries,
):
if (
manifest["id"]
!= DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_PATCH_ID
):
die("Device Control Core migration recovery patch id mismatch")
validate_device_plane_control_core_migration_replay_recovery_payload(
payload_dir
)
if is_device_plane_postgres_bootstrap_slice(
manifest["component"],
entries,
@@ -11931,6 +12010,18 @@ def is_device_plane_control_core_incident_audit_slice(component, entries):
)
def is_device_plane_control_core_migration_replay_recovery_slice(
component,
entries,
):
return (
component == "device-plane"
and entries is not None
and tuple(entries)
== DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_ENTRIES
)
def is_device_plane_manager_v2_control_plane_slice(component, entries):
return (
component == "device-plane"
@@ -12670,6 +12761,54 @@ def expected_device_plane_control_core_incident_audit_descriptor():
}
def expected_device_plane_control_core_migration_replay_recovery_descriptor():
return {
"schemaVersion": (
"nodedc.device-plane."
"device-control-core-migration-replay-recovery.v1"
),
"mode": "double-rollback-failed-migration-014-forward-repair",
"failedIncidentAudit": (
DEVICE_PLANE_CONTROL_CORE_INCIDENT_AUDIT_PATCH_ID
),
"sourcePredecessor": {
"path": DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_REL,
"sha256": (
DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_PREDECESSOR_SHA256
),
},
"sourceTarget": {
"path": DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_REL,
"sha256": DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_TARGET_SHA256,
},
"rootCause": (
"intermediate-command-kind-check-revalidated-historical-receipts"
),
"repair": "migration-014-add-constraint-not-valid",
"databasePreflight": (
"all-live-command-kinds-covered-by-final-migration-016"
),
"databaseRowMutation": "none",
"databaseSchemaOutcome": (
"final-migration-016-validated-command-kind-check"
),
"runtimeAction": "build+recreate-device-control-core-only",
"runtimePredecessor": "proven-degraded-double-rollback-state",
"preservedServices": [
"device-manager",
"device-gateway",
"device-postgres",
"device-backhaul-target",
],
"databaseVolume": DEVICE_PLANE_POSTGRES_VOLUME,
"publicIngress": "disabled",
"edgeChannel": (
"core-initiated-pinned-mtls-registered-edges-only"
),
"rollback": "source+exact-degraded-predecessor-image-runtime",
}
def validate_platform_device_core_hub_trust_payload(payload_dir):
descriptor = read_strict_json(
payload_dir / PLATFORM_DEVICE_CORE_HUB_TRUST_REL,
@@ -13572,6 +13711,41 @@ def validate_device_plane_control_core_incident_audit_payload(payload_dir):
return descriptor
def validate_device_plane_control_core_migration_replay_recovery_payload(
payload_dir,
):
descriptor = read_strict_json(
payload_dir
/ DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_REL,
"Device Control Core migration replay recovery descriptor",
max_bytes=16 * 1024,
)
if (
descriptor
!= expected_device_plane_control_core_migration_replay_recovery_descriptor()
):
die("Device Control Core migration replay recovery descriptor mismatch")
migration = payload_dir / DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_REL
try:
migration_stat = migration.lstat()
migration_text = migration.read_text(encoding="utf-8")
except (FileNotFoundError, OSError, UnicodeDecodeError):
die("Device Control Core migration 014 repair is unreadable")
if (
stat.S_ISLNK(migration_stat.st_mode)
or not stat.S_ISREG(migration_stat.st_mode)
or sha256_file(migration)
!= DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_TARGET_SHA256
or ")) not valid;" not in migration_text.lower()
or re.search(
r"(?im)^\s*(?:delete|update|insert|truncate)\b",
migration_text,
)
):
die("Device Control Core migration 014 repair mismatch")
return descriptor
def is_device_plane_postgres_bootstrap_slice(component, entries):
return (
component == "device-plane"
@@ -16417,6 +16591,12 @@ def validate_device_plane_control_core_incident_audit_evidence(payload_dir):
descriptor = validate_device_plane_control_core_incident_audit_payload(
payload_dir
)
evidence = validate_device_plane_control_core_double_failure_evidence()
evidence["mode"] = descriptor["mode"]
return evidence
def validate_device_plane_control_core_double_failure_evidence():
first_backup = validate_device_plane_control_core_v3_reconciliation_backup()
first_failed_artifact = (
FAILED_DIR / DEVICE_PLANE_CONTROL_CORE_V3_FAILED_ARTIFACT
@@ -16570,13 +16750,282 @@ def validate_device_plane_control_core_incident_audit_evidence(payload_dir):
"device-backhaul-target",
))
return {
"mode": descriptor["mode"],
"mode": "double-rollback-failed-evidence",
"firstBackup": first_backup,
"secondBackup": backup_dir,
"runtime": current,
}
def collect_device_plane_control_core_migration_replay_database_evidence():
postgres_ids = device_plane_service_container_ids("device-postgres")
if len(postgres_ids) != 1:
die("Device Control Core migration recovery PostgreSQL is missing")
allowed = ",".join(
"'" + value.replace("'", "''") + "'"
for value in DEVICE_PLANE_CONTROL_CORE_FINAL_COMMAND_KINDS
)
triggering = ",".join(
"'" + value.replace("'", "''") + "'"
for value in DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_TRIGGER_KINDS
)
query = f"""
with constraint_state as (
select convalidated,
(select bool_and(pg_get_constraintdef(c.oid) like '%' || kind || '%')
from unnest(array[{allowed}]::text[]) as kind) as covers_final
from pg_constraint c
where c.conrelid = 'public.device_management_command_receipts'::regclass
and c.conname = 'device_management_command_receipts_command_kind_check'
)
select (
select count(*)
from device_management_command_receipts
where not (command_kind = any(array[{allowed}]::text[]))
)::text,
(
select count(*)
from device_management_command_receipts
where command_kind = any(array[{triggering}]::text[])
)::text,
coalesce((select convalidated::text from constraint_state), 'missing'),
coalesce((select covers_final::text from constraint_state), 'false'),
(to_regclass('public.device_infrastructure_host_telemetry_samples')
is null)::text
""".strip()
result = subprocess.run(
[
str(DOCKER),
"exec",
postgres_ids[0],
"psql",
"-X",
"-qAt",
"-v",
"ON_ERROR_STOP=1",
"-U",
"device_plane",
"-d",
"device_plane",
"-F",
"\t",
"-c",
query,
],
check=False,
capture_output=True,
text=True,
timeout=30,
)
values = result.stdout.strip().split("\t")
if (
result.returncode != 0
or result.stderr.strip()
or len(values) != 5
or not re.fullmatch(r"[0-9]+", values[0])
or not re.fullmatch(r"[0-9]+", values[1])
or values[2] not in ("true", "false", "missing")
or values[3] not in ("true", "false")
or values[4] not in ("true", "false")
):
die("Device Control Core migration recovery database read failed")
evidence = {
"invalidCommandKindCount": int(values[0]),
"triggeringReceiptCount": int(values[1]),
"constraintValidated": values[2] == "true",
"constraintCoversFinalKinds": values[3] == "true",
"hostTelemetryTableAbsent": values[4] == "true",
"query": query,
}
if (
evidence["invalidCommandKindCount"] != 0
or evidence["triggeringReceiptCount"] < 1
or not evidence["constraintValidated"]
or not evidence["constraintCoversFinalKinds"]
or not evidence["hostTelemetryTableAbsent"]
):
die("Device Control Core migration recovery database invariant mismatch")
return evidence
def validate_device_plane_control_core_migration_replay_preserved_runtime(
evidence,
):
expected_services = {
"device-control-core",
"device-manager",
"device-gateway",
"device-postgres",
"device-backhaul-target",
}
current = device_plane_runtime_inventory(tuple(sorted(expected_services)))
if set(device_plane_inventory_service_names(current)) != expected_services:
die("Device Control Core migration recovery runtime is incomplete")
second_before = read_strict_json(
evidence["secondBackup"] / "runtime-before.json",
"Device Control Core second failed-apply runtime inventory",
max_bytes=64 * 1024,
)
if set(device_plane_inventory_service_names(second_before)) != expected_services:
die("Device Control Core second failed-apply runtime evidence mismatch")
before = {item["service"]: item for item in second_before["services"]}
observed = {item["service"]: item for item in current["services"]}
for service in expected_services - {"device-control-core"}:
if (
observed[service]["containerId"] != before[service]["containerId"]
or observed[service]["imageId"] != before[service]["imageId"]
or observed[service]["status"] != "running"
or observed[service]["running"] is not True
or observed[service]["health"] != "healthy"
):
die(
"Device Control Core migration recovery changed preserved "
f"service: {service}"
)
return {"current": current, "core": observed["device-control-core"]}
def validate_device_plane_control_core_migration_replay_recovery_evidence(
payload_dir,
):
descriptor = (
validate_device_plane_control_core_migration_replay_recovery_payload(
payload_dir
)
)
evidence = validate_device_plane_control_core_double_failure_evidence()
root = component_root("device-plane")
live_migration = root / DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_REL
if (
live_migration.is_symlink()
or not live_migration.is_file()
or sha256_file(live_migration)
!= DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_PREDECESSOR_SHA256
):
die("Device Control Core migration 014 predecessor mismatch")
installed_descriptor = (
root / DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_REL
)
if installed_descriptor.exists() or installed_descriptor.is_symlink():
die("Device Control Core migration replay recovery already installed")
runtime = (
validate_device_plane_control_core_migration_replay_preserved_runtime(
evidence
)
)
core = runtime["core"]
if (
core["imageId"] != DEVICE_PLANE_CONTROL_CORE_V3_PREAPPLY_IMAGE_ID
or core["status"] not in ("running", "restarting", "exited")
or core["health"] not in ("starting", "unhealthy", None)
):
die("Device Control Core migration recovery predecessor mismatch")
image_id = inspect_optional_local_image(
DEVICE_PLANE_CONTROL_CORE_V3_PREAPPLY_IMAGE_ID,
"Device Control Core migration recovery exact predecessor image",
)
if image_id != DEVICE_PLANE_CONTROL_CORE_V3_PREAPPLY_IMAGE_ID:
die("Device Control Core migration recovery predecessor image is missing")
database = (
collect_device_plane_control_core_migration_replay_database_evidence()
)
return {
"mode": descriptor["mode"],
"descriptor": descriptor,
"firstBackup": evidence["firstBackup"],
"secondBackup": evidence["secondBackup"],
"runtime": runtime["current"],
"core": core,
"database": database,
}
def accept_device_plane_control_core_migration_replay_recovery():
root = component_root("device-plane")
migration = root / DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_REL
if (
migration.is_symlink()
or not migration.is_file()
or sha256_file(migration)
!= DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_TARGET_SHA256
):
die("installed Device Control Core migration 014 repair mismatch")
descriptor = read_strict_json(
root / DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_REL,
"installed Device Control Core migration replay recovery descriptor",
max_bytes=16 * 1024,
)
if (
descriptor
!= expected_device_plane_control_core_migration_replay_recovery_descriptor()
):
die("installed Device Control Core migration recovery mismatch")
evidence = {
"secondBackup": (
BACKUPS_DIR
/ DEVICE_PLANE_CONTROL_CORE_V3_RECONCILIATION_FAILED_BACKUP_ID
)
}
runtime = (
validate_device_plane_control_core_migration_replay_preserved_runtime(
evidence
)
)
core = runtime["core"]
if (
core["imageId"] == DEVICE_PLANE_CONTROL_CORE_V3_PREAPPLY_IMAGE_ID
or core["status"] != "running"
or core["running"] is not True
or core["health"] != "healthy"
):
die("Device Control Core migration recovery did not converge")
database = (
collect_device_plane_control_core_migration_replay_database_evidence()
)
validate_device_manager_control_plane_runtime(
require_edge_channel=True,
core_network_mode="private-egress",
)
return {"runtime": runtime["current"], "database": database}
def emit_bounded_device_control_core_failure_logs():
core_ids = device_plane_service_container_ids("device-control-core")
if len(core_ids) != 1:
return
result = subprocess.run(
[str(DOCKER), "logs", "--tail", "160", core_ids[0]],
check=False,
capture_output=True,
text=True,
timeout=30,
)
if result.returncode != 0:
return
selected = []
for raw_line in f"{result.stdout}\n{result.stderr}".splitlines():
line = re.sub(r"\s+", " ", raw_line.strip())
if not line or not re.search(
r"(?:error|exception|failed|constraint|migration|postgres|relation)",
line,
re.IGNORECASE,
):
continue
if re.search(
r"(?:authorization|bearer|password|private[_ -]?key|token=|secret=)",
line,
re.IGNORECASE,
):
line = "[sensitive log line redacted]"
if line not in selected:
selected.append(line[:480])
for index, line in enumerate(selected[-16:], start=1):
print(
f"device_control_core_failure_log_{index:02d}={line}",
file=sys.stderr,
)
def collect_device_plane_control_core_incident_audit():
core_ids = device_plane_service_container_ids("device-control-core")
postgres_ids = device_plane_service_container_ids("device-postgres")
@@ -16849,6 +17298,25 @@ def accept_device_plane_control_core_rollback_runtime(runtime_before):
for service in expected_services[1:]:
healthcheck_compose_service_with_grace("device-plane", service)
preserved = device_plane_runtime_inventory(expected_services[1:])
if set(device_plane_inventory_service_names(preserved)) != set(
expected_services[1:]
):
die("Device Control Core rollback preserved runtime is incomplete")
for item in preserved["services"]:
expected = before[item["service"]]
if (
item["containerId"] != expected["containerId"]
or item["imageId"] != expected["imageId"]
or item["status"] != "running"
or item["running"] is not True
or item["health"] != "healthy"
):
die(
"Device Control Core rollback changed preserved service: "
f"{item['service']}"
)
container_id = compose_service_container_id(
"device-plane",
"device-control-core",
@@ -20079,6 +20547,12 @@ def component_services(component, entries=None):
if is_device_plane_control_core_incident_audit_slice(component, entries):
return ()
if is_device_plane_control_core_migration_replay_recovery_slice(
component,
entries,
):
return ("device-control-core",)
if is_device_plane_manager_only_release_slice(component, entries):
return ("device-manager",)
@@ -20688,6 +21162,24 @@ def component_builds(component, entries=None):
if is_device_plane_control_core_incident_audit_slice(component, entries):
return ()
if is_device_plane_control_core_migration_replay_recovery_slice(
component,
entries,
):
return ((
DEVICE_PLANE_ROOT,
(
"build",
"--no-cache",
"--network=host",
"-f",
"services/device-control-core/Dockerfile",
"-t",
DEVICE_PLANE_CONTROL_CORE_IMAGE,
".",
),
),)
if is_device_plane_manager_only_release_slice(component, entries):
return ((
DEVICE_PLANE_ROOT / "services/device-manager",
@@ -28882,6 +29374,7 @@ def plan_artifact(artifact):
device_plane_manager_v2_reconciliation_preflight = None
device_plane_control_core_v3_reconciliation_preflight = None
device_plane_control_core_incident_audit_preflight = None
device_plane_control_core_migration_replay_recovery_preflight = None
device_plane_backhaul_preflight = None
device_plane_backhaul_vps_enrollment_preflight = None
device_plane_runtime_before = None
@@ -29165,6 +29658,20 @@ def plan_artifact(artifact):
collect_device_plane_control_core_incident_audit()
)
device_plane_control_core_incident_audit_preflight = incident
if is_device_plane_control_core_migration_replay_recovery_slice(
manifest["component"],
entries,
):
if (
manifest["id"]
!= DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_PATCH_ID
):
die("Device Control Core migration recovery patch id mismatch")
device_plane_control_core_migration_replay_recovery_preflight = (
validate_device_plane_control_core_migration_replay_recovery_evidence(
payload_dir
)
)
if is_device_plane_backhaul_target_slice(
manifest["component"],
entries,
@@ -31383,6 +31890,65 @@ def plan_artifact(artifact):
"read-only:device-control-core,device-manager,device-gateway,"
"device-postgres,device-backhaul-target"
)
if (
device_plane_control_core_migration_replay_recovery_preflight
is not None
):
recovery = (
device_plane_control_core_migration_replay_recovery_preflight
)
database = recovery["database"]
core = recovery["core"]
print(f"device_plane_transition={recovery['mode']}")
print(
"device_control_core_root_cause="
"migration-014-intermediate-constraint-revalidated-"
"newer-valid-receipts"
)
print(
"device_control_core_migration_predecessor_sha256="
f"{DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_PREDECESSOR_SHA256}"
)
print(
"device_control_core_migration_target_sha256="
f"{DEVICE_PLANE_CONTROL_CORE_MIGRATION_014_TARGET_SHA256}"
)
print(
"device_control_core_current_runtime="
f"{core['containerId']}:{core['imageId']}:"
f"{core['status']}:{core['health']}:"
f"restarts={core['restartCount']}"
)
print(
"device_control_core_live_command_kind_incompatible_count="
f"{database['invalidCommandKindCount']}"
)
print(
"device_control_core_triggering_newer_receipt_count="
f"{database['triggeringReceiptCount']}"
)
print(
"device_control_core_final_constraint="
"validated:covers-migration-016-command-kinds"
)
print("device_postgres_row_mutation=none")
print("device_postgres_telemetry_table=absent")
print(
"device_plane_runtime_mutation="
"build+recreate:device-control-core"
)
print(
"device_plane_runtime_services="
"preserved:device-manager,device-gateway,device-postgres,"
"device-backhaul-target"
)
print("device_gateway_public_ingress=disabled")
print("device_gateway_tcp_9921=preserved:loopback-only")
print("gelios=untouched-legacy-only")
print(
"device_plane_rollback="
"source+exact-degraded-predecessor-image-runtime"
)
if device_plane_backhaul_vps_enrollment_preflight is not None:
print(
"device_plane_transition="
@@ -31990,9 +32556,15 @@ def rollback_device_plane_apply(
if not runtime_started or not baseline_services:
return f"source-restored-runtime-unchanged:{restored_count}"
control_core_release_rollback = is_device_plane_control_core_release_slice(
"device-plane",
entries,
control_core_release_rollback = (
is_device_plane_control_core_release_slice(
"device-plane",
entries,
)
or is_device_plane_control_core_migration_replay_recovery_slice(
"device-plane",
entries,
)
)
if control_core_release_rollback:
before = {
@@ -33598,6 +34170,21 @@ def component_healthchecks(component, entries=None, services=None):
"deviceCoreInternalAccessConfigured": True,
},
},)
if is_device_plane_control_core_migration_replay_recovery_slice(
component,
entries,
):
return ({
"url": "http://127.0.0.1:18120/healthz",
"expected_json": {
"ok": True,
"service": "nodedc-device-control-core",
"database": "ready",
"discoveryIngest": "enabled",
"managementApi": "enabled",
"commandTransport": "typed-service-ping-v1",
},
},)
if is_device_plane_manager_control_plane_slice(component, entries):
command_transport = (
"typed-service-ping-v1"
@@ -34633,6 +35220,35 @@ def run_healthchecks(component, entries=None, services=None):
)
return
if is_device_plane_control_core_migration_replay_recovery_slice(
component,
entries,
):
if tuple(services or ()) != ("device-control-core",):
die("Device Control Core migration recovery service set mismatch")
try:
healthcheck_compose_service_with_grace(
"device-plane",
"device-control-core",
)
except DeployError:
emit_bounded_device_control_core_failure_logs()
raise
for service in (
"device-manager",
"device-gateway",
"device-postgres",
"device-backhaul-target",
):
healthcheck_compose_service_with_grace(
"device-plane",
service,
)
for check in component_healthchecks(component, entries, services):
healthcheck_url(check)
accept_device_plane_control_core_migration_replay_recovery()
return
if is_device_plane_control_core_release_slice(component, entries):
if tuple(services or ()) != ("device-control-core",):
die("Device Control Core release service set mismatch")
@@ -35782,6 +36398,21 @@ def apply_artifact(artifact):
validate_device_plane_control_core_v3_reconciliation_evidence(
payload_dir
)
if is_device_plane_control_core_migration_replay_recovery_slice(
component,
entries,
):
if (
patch_id
!= DEVICE_PLANE_CONTROL_CORE_MIGRATION_REPLAY_RECOVERY_PATCH_ID
):
die(
"Device Control Core migration recovery patch id "
"mismatch"
)
validate_device_plane_control_core_migration_replay_recovery_evidence(
payload_dir
)
if is_device_plane_backhaul_target_slice(
component,
entries,
@@ -36104,6 +36735,10 @@ def apply_artifact(artifact):
component,
entries,
)
or is_device_plane_control_core_migration_replay_recovery_slice(
component,
entries,
)
):
inventory_services = (
*inventory_services,