"""VPG status / substatus integers from GET /v1/vpgs/statuses and /substatuses. Live 10.9 ZVM (192.168.50.30, 2026-09-21). Older api_lessons mapping (0=Protecting, 1=Moving) is wrong on this appliance. """ # GET /v1/vpgs/statuses INITIALIZING = 0 MEETING_SLA = 1 NOT_MEETING_SLA = 2 RPO_NOT_MEETING_SLA = 3 HISTORY_NOT_MEETING_SLA = 4 FAILING_OVER = 5 MOVING = 6 DELETING = 7 RECOVERED = 8 STATUS_NAME = { INITIALIZING: "Initializing", MEETING_SLA: "MeetingSLA", NOT_MEETING_SLA: "NotMeetingSLA", RPO_NOT_MEETING_SLA: "RpoNotMeetingSLA", HISTORY_NOT_MEETING_SLA: "HistoryNotMeetingSLA", FAILING_OVER: "FailingOver", MOVING: "Moving", DELETING: "Deleting", RECOVERED: "Recovered", } # GET /v1/vpgs/substatuses NONE = 0 INITIAL_SYNC = 1 CREATING = 2 VOLUME_INITIAL_SYNC = 3 SYNC = 4 RECOVERY_POSSIBLE = 5 DELTA_SYNC = 6 NEEDS_CONFIGURATION = 7 ERROR = 8 EMPTY_PROTECTION_GROUP = 9 DISCONNECTED_NO_RECOVERY_POINTS = 10 FULL_SYNC = 11 VOLUME_DELTA_SYNC = 12 VOLUME_FULL_SYNC = 13 FAILING_OVER_COMMITTING = 14 FAILING_OVER_BEFORE_COMMIT = 15 FAILING_OVER_ROLLING_BACK = 16 PROMOTING = 17 MOVING_COMMITTING = 18 MOVING_BEFORE_COMMIT = 19 MOVING_ROLLING_BACK = 20 DELETING_SUB = 21 PENDING_REMOVE = 22 BITMAP_SYNC = 23 DISCONNECTED_FROM_PEER = 24 REPLICATION_PAUSED_USER = 25 REPLICATION_PAUSED_SYSTEM = 26 ADDED_VMS_IN_INITIAL_SYNC = 34 SUBSTATUS_NAME = { NONE: "None", INITIAL_SYNC: "InitialSync", CREATING: "Creating", VOLUME_INITIAL_SYNC: "VolumeInitialSync", SYNC: "Sync", RECOVERY_POSSIBLE: "RecoveryPossible", DELTA_SYNC: "DeltaSync", NEEDS_CONFIGURATION: "NeedsConfiguration", ERROR: "Error", EMPTY_PROTECTION_GROUP: "EmptyProtectionGroup", DISCONNECTED_NO_RECOVERY_POINTS: "DisconnectedFromPeerNoRecoveryPoints", FULL_SYNC: "FullSync", VOLUME_DELTA_SYNC: "VolumeDeltaSync", VOLUME_FULL_SYNC: "VolumeFullSync", FAILING_OVER_COMMITTING: "FailingOverCommitting", FAILING_OVER_BEFORE_COMMIT: "FailingOverBeforeCommit", FAILING_OVER_ROLLING_BACK: "FailingOverRollingBack", PROMOTING: "Promoting", MOVING_COMMITTING: "MovingCommitting", MOVING_BEFORE_COMMIT: "MovingBeforeCommit", MOVING_ROLLING_BACK: "MovingRollingBack", DELETING_SUB: "Deleting", PENDING_REMOVE: "PendingRemove", BITMAP_SYNC: "BitmapSync", DISCONNECTED_FROM_PEER: "DisconnectedFromPeer", REPLICATION_PAUSED_USER: "ReplicationPausedUserInitiated", REPLICATION_PAUSED_SYSTEM: "ReplicationPausedSystemInitiated", ADDED_VMS_IN_INITIAL_SYNC: "AddedVmsInInitialSync", } SYNCING = { INITIAL_SYNC, CREATING, VOLUME_INITIAL_SYNC, SYNC, DELTA_SYNC, FULL_SYNC, VOLUME_DELTA_SYNC, VOLUME_FULL_SYNC, BITMAP_SYNC, ADDED_VMS_IN_INITIAL_SYNC, } TAGGABLE_STATUS = { MEETING_SLA, NOT_MEETING_SLA, RPO_NOT_MEETING_SLA, HISTORY_NOT_MEETING_SLA, } def status_name(value: int | None) -> str: if value is None: return "unknown" return STATUS_NAME.get(value, f"status:{value}") def substatus_name(value: int | None) -> str: if value is None: return "unknown" return SUBSTATUS_NAME.get(value, f"substatus:{value}") def can_tag(status: int | None, substatus: int | None) -> tuple[bool, str | None]: """Whether a tagged checkpoint can be inserted on this VPG right now.""" if status not in TAGGABLE_STATUS: return False, f"VPG status is {status_name(status)}; not MeetingSLA" if substatus in SYNCING: return False, ( f"VPG is {substatus_name(substatus)}; " "checkpoints are not durable until sync ends" ) return True, None