feat(poc): rewind MCP, skill, and recover-ladder docs
Initial PoC: find_protection, tagged checkpoints, FLR, mutating catalog. Lab 10.9 status enums (0=Initializing, 1=MeetingSLA). Credentials stay in gitignored config.json.
This commit is contained in:
commit
38ba9c1b50
24 files changed
+1811
No files matched your search
@@ -0,0 +1,133 @@
|
||||
"""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
|
||||
Reference in new issue
Block a user