ce7cb702218693d08ea6d83464d2457c9250027c

This commit is contained in:
ms2k 2026-11-12 20:46:28 +09:00
commit 34c5f8963c
22 changed files with 145336 additions and 0 deletions

333
docs/spec/tier-s/Cloud.tla Normal file
View file

@ -0,0 +1,333 @@
------------------------------- MODULE Cloud -------------------------------
EXTENDS Naturals, FiniteSets, TLC
CONSTANTS Mode, Scenario, ResourceKind, LoseReply, RestartOnce, DelayLists
(* This projection separates OCI resource state, API observations, and publication. *)
(* cloud.Client.Reconcile supplies the create/select/cleanup protocol for each kind. *)
Kinds == {"CPE", "VPN"}
Modes == {"Current", "Fixed"}
Cases == {"Retry", "Routes"}
Ids == 1..3
WANs == {"A", "B"}
VIPs == {"X", "Y"}
Attempts == 0..2
Keys == WANs \X Attempts
Lives == {"Unused", "Provisioning", "Available", "Terminating", "Terminated", "Absent"}
Phases == {"read", "create", "reply", "inspect", "clean", "admit", "publish", "pause"}
ASSUME /\ Mode \in Modes
/\ Scenario \in Cases
/\ ResourceKind \in Kinds
/\ Scenario = "Routes" => ResourceKind = "VPN"
/\ LoseReply \in BOOLEAN
/\ RestartOnce \in BOOLEAN
/\ DelayLists \in BOOLEAN
VARIABLES objects, visible, tokens, invalid, issued, nextId, epoch,
phase, seen, selected, attempt, reply, routeSeen, pending,
health, published, admitted, todo, refs, dropped, restarted, badPublish
vars == <<objects, visible, tokens, invalid, issued, nextId, epoch,
phase, seen, selected, attempt, reply, routeSeen, pending,
health, published, admitted, todo, refs, dropped, restarted, badPublish>>
LastEpoch == IF Scenario = "Retry" THEN 2 ELSE 1
WAN == IF Scenario = "Retry" /\ epoch = 1 THEN "B" ELSE "A"
VIP == IF Scenario = "Routes" /\ epoch = 1 THEN "Y" ELSE "X"
Key == <<WAN, attempt>>
Active == {i \in Ids : objects[i].life \in {"Provisioning", "Available"}}
Present == {i \in Ids : objects[i].life \notin {"Unused", "Absent"}}
Current == {i \in seen : objects[i].wan = WAN /\
(ResourceKind = "CPE" \/
objects[i].life \notin {"Terminating", "Terminated", "Absent"})}
Old == {i \in seen : i # selected}
Init == /\ objects = [i \in Ids |-> [life |-> "Unused", wan |-> "A", route |-> "X"]]
/\ visible = {}
/\ tokens = [k \in Keys |-> 0]
/\ invalid = {}
/\ issued = {}
/\ nextId = 1
/\ epoch = 0
/\ phase = "read"
/\ seen = {}
/\ selected = 0
/\ attempt = 0
/\ reply = 0
/\ routeSeen = "X"
/\ pending = [i \in Ids |-> "None"]
/\ health = {}
/\ published = [epoch |-> 3, id |-> 0, route |-> "X"]
/\ admitted = {}
/\ todo = {}
/\ refs = {}
/\ dropped = FALSE
/\ restarted = FALSE
/\ badPublish = FALSE
(* cloud.Client.Reconcile lists before selecting a CPE or a non-terminating VPN. *)
Read == /\ phase = "read"
/\ seen' = visible
/\ phase' = "inspect"
/\ selected' = 0
/\ attempt' = 0
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
reply, routeSeen, pending, health, published, admitted, todo,
refs, dropped, restarted, badPublish>>
Select == /\ phase = "inspect" /\ selected = 0
/\ IF Cardinality(Current) = 1
THEN /\ selected' = CHOOSE i \in Current : TRUE
/\ routeSeen' = objects[selected'].route
/\ phase' = "inspect"
ELSE /\ selected' = 0
/\ UNCHANGED routeSeen
/\ phase' = IF Current = {} THEN "create" ELSE "pause"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, attempt, reply, pending, health, published, admitted,
todo, refs, dropped, restarted, badPublish>>
(* OCI Retry Token and InvalidatedRetryToken define these three create outcomes. *)
(* https://docs.oracle.com/en-us/iaas/Content/API/References/apierrors.htm *)
Create == /\ phase = "create"
/\ Key \notin invalid
/\ tokens[Key] = 0
/\ nextId \in Ids
/\ objects' = [objects EXCEPT ![nextId] =
[life |-> IF ResourceKind = "VPN" THEN "Provisioning" ELSE "Available",
wan |-> WAN, route |-> VIP]]
/\ tokens' = [tokens EXCEPT ![Key] = nextId]
/\ issued' = issued \cup {<<Key, nextId>>}
/\ reply' = nextId
/\ nextId' = nextId + 1
/\ visible' = IF DelayLists THEN visible ELSE visible \cup {nextId}
/\ phase' = "reply"
/\ UNCHANGED <<invalid, epoch, seen, selected, attempt, routeSeen, pending,
health, published, admitted, todo, refs, dropped,
restarted, badPublish>>
Replay == /\ phase = "create" /\ Key \notin invalid /\ tokens[Key] # 0
/\ reply' = tokens[Key]
/\ phase' = "reply"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, selected, attempt, routeSeen, pending, health,
published, admitted, todo, refs, dropped, restarted, badPublish>>
(* Fixed follows a deterministic successor only on InvalidatedRetryToken; restart replays that chain. *)
Reject == /\ phase = "create" /\ Key \in invalid
/\ IF Mode = "Fixed" /\ attempt < 2
THEN /\ attempt' = attempt + 1 /\ phase' = "create"
ELSE /\ UNCHANGED attempt /\ phase' = "pause"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, selected, reply, routeSeen, pending, health, published,
admitted, todo, refs, dropped, restarted, badPublish>>
Receive == /\ phase = "reply"
/\ selected' = reply
/\ routeSeen' = objects[reply].route
/\ seen' = seen \cup {reply}
/\ phase' = "inspect"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
attempt, reply, pending, health, published, admitted, todo,
refs, dropped, restarted, badPublish>>
(* A timed-out create may already have committed; only its response is lost. *)
DropReply == /\ LoseReply /\ ~dropped /\ phase = "reply"
/\ dropped' = TRUE
/\ phase' = "read"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, selected, attempt, reply, routeSeen, pending, health,
published, admitted, todo, refs, restarted, badPublish>>
Restart == /\ RestartOnce /\ ~restarted
/\ restarted' = TRUE
/\ phase' = "read"
/\ selected' = 0
/\ attempt' = 0
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, reply, routeSeen, pending, health, published, admitted,
todo, refs, dropped, badPublish>>
(* UpdateIPSecConnectionDetails.StaticRoutes replaces the managed route set. *)
UpdateRoute == /\ phase = "inspect" /\ selected # 0
/\ objects[selected].life = "Available"
/\ ResourceKind = "VPN" /\ Mode = "Fixed" /\ routeSeen # VIP
/\ pending' = [pending EXCEPT ![selected] = VIP]
/\ phase' = "pause"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId,
epoch, seen, selected, attempt, reply, routeSeen, health,
published, admitted, todo, refs, dropped, restarted, badPublish>>
(* CPE unavailability here represents a rejected child-IPsec call, not a readable CPE lifecycle. *)
WaitReady == /\ phase = "inspect" /\ selected # 0
/\ objects[selected].life # "Available"
/\ phase' = "pause"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, selected, attempt, reply, routeSeen, pending, health,
published, admitted, todo, refs, dropped, restarted, badPublish>>
BeginClean == /\ phase = "inspect" /\ selected # 0
/\ objects[selected].life = "Available"
/\ ResourceKind = "CPE" \/ Mode = "Current" \/ routeSeen = VIP
/\ todo' = IF selected \in health THEN Old ELSE {}
/\ phase' = "clean"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, selected, attempt, reply, routeSeen, pending, health,
published, admitted, refs, dropped, restarted, badPublish>>
(* CPE disposal follows child-IPsec retirement; this abstracts that completed subprotocol. *)
RetireChild(i) == /\ ResourceKind = "CPE" /\ phase = "clean" /\ i \in todo /\ i \in refs
/\ refs' = refs \ {i}
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId,
epoch, phase, seen, selected, attempt, reply, routeSeen,
pending, health, published, admitted, todo, dropped,
restarted, badPublish>>
Delete(i) == /\ phase = "clean" /\ i \in todo /\ i \notin refs
/\ objects' = IF i \in Active
THEN [objects EXCEPT ![i].life = "Terminating"]
ELSE objects
/\ todo' = todo \ {i}
/\ health' = health \ {i}
/\ UNCHANGED <<visible, tokens, invalid, issued, nextId, epoch, phase,
seen, selected, attempt, reply, routeSeen, pending,
published, admitted, refs, dropped, restarted, badPublish>>
CleanDone == /\ phase = "clean" /\ todo = {}
/\ phase' = "admit"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, selected, attempt, reply, routeSeen, pending, health,
published, admitted, todo, refs, dropped, restarted, badPublish>>
Admit == /\ phase = "admit"
/\ admitted' = {i \in seen : objects[i].life = "Available"}
/\ phase' = "publish"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, selected, attempt, reply, routeSeen, pending, health,
published, todo, refs, dropped, restarted, badPublish>>
(* controller.Runner.step publishes after admission and two retrievable peer configurations. *)
Publish == /\ phase = "publish"
/\ published' = [epoch |-> epoch, id |-> selected, route |-> VIP]
/\ badPublish' = (badPublish \/ (ResourceKind = "VPN" /\ routeSeen # VIP))
/\ refs' = IF ResourceKind = "CPE" THEN refs \cup {selected} ELSE refs
/\ phase' = "pause"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, selected, attempt, reply, routeSeen, pending, health,
admitted, todo, dropped, restarted>>
Poll == /\ phase = "pause" /\ phase' = "read"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, epoch,
seen, selected, attempt, reply, routeSeen, pending, health,
published, admitted, todo, refs, dropped, restarted, badPublish>>
Provision(i) == /\ objects[i].life = "Provisioning"
/\ objects' = [objects EXCEPT ![i].life = "Available"]
/\ UNCHANGED <<visible, tokens, invalid, issued, nextId, epoch,
phase, seen, selected, attempt, reply, routeSeen, pending,
health, published, admitted, todo, refs, dropped,
restarted, badPublish>>
Expose(i) == /\ i \in Present /\ i \notin visible
/\ visible' = visible \cup {i}
/\ UNCHANGED <<objects, tokens, invalid, issued, nextId, epoch, phase,
seen, selected, attempt, reply, routeSeen, pending, health,
published, admitted, todo, refs, dropped, restarted, badPublish>>
Finish(i) == /\ objects[i].life = "Terminating"
/\ objects' = [objects EXCEPT ![i].life =
IF ResourceKind = "VPN" THEN "Terminated" ELSE "Absent"]
/\ invalid' = invalid \cup {k \in Keys : tokens[k] = i}
/\ UNCHANGED <<visible, tokens, issued, nextId, epoch, phase, seen,
selected, attempt, reply, routeSeen, pending, health,
published, admitted, todo, refs, dropped, restarted, badPublish>>
Purge(i) == /\ objects[i].life = "Terminated"
/\ objects' = [objects EXCEPT ![i].life = "Absent"]
/\ UNCHANGED <<visible, tokens, invalid, issued, nextId, epoch, phase,
seen, selected, attempt, reply, routeSeen, pending, health,
published, admitted, todo, refs, dropped, restarted, badPublish>>
Forget(i) == /\ objects[i].life = "Absent" /\ i \in visible
/\ visible' = visible \ {i}
/\ UNCHANGED <<objects, tokens, invalid, issued, nextId, epoch, phase,
seen, selected, attempt, reply, routeSeen, pending, health,
published, admitted, todo, refs, dropped, restarted, badPublish>>
ApplyRoute(i) == /\ pending[i] \in VIPs /\ objects[i].life = "Available"
/\ objects' = [objects EXCEPT ![i].route = pending[i]]
/\ pending' = [pending EXCEPT ![i] = "None"]
/\ UNCHANGED <<visible, tokens, invalid, issued, nextId, epoch,
phase, seen, selected, attempt, reply, routeSeen,
health, published, admitted, todo, refs, dropped,
restarted, badPublish>>
(* health denotes both associated IPsec tunnels being up; CPE itself has no health field. *)
Establish(i) == /\ published.id = i /\ objects[i].life = "Available"
/\ objects[i].wan = WAN /\ i \notin health
/\ health' = health \cup {i}
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId,
epoch, phase, seen, selected, attempt, reply, routeSeen,
pending, published, admitted, todo, refs, dropped,
restarted, badPublish>>
Converged == /\ published.epoch = epoch /\ published.id \in health
/\ objects[published.id].wan = WAN
/\ ResourceKind = "CPE" \/ objects[published.id].route = VIP
Advance == /\ epoch < LastEpoch /\ phase = "pause" /\ Converged
/\ \A i \in Ids : i = published.id \/ objects[i].life \in {"Unused", "Absent"}
/\ visible = {published.id}
/\ epoch' = epoch + 1
/\ health' = {}
/\ phase' = "read"
/\ UNCHANGED <<objects, visible, tokens, invalid, issued, nextId, seen,
selected, attempt, reply, routeSeen, pending, published,
admitted, todo, refs, dropped, restarted, badPublish>>
Work == Read \/ Select \/ Create \/ Replay \/ Reject \/ Receive \/ UpdateRoute \/
WaitReady \/ BeginClean \/ CleanDone \/ Admit \/ Publish \/ Poll \/
(\E i \in Ids : RetireChild(i) \/ Delete(i))
Provider(i) == Provision(i) \/ Expose(i) \/ Finish(i) \/ Purge(i) \/ Forget(i) \/
ApplyRoute(i) \/ Establish(i)
Next == Work \/ Advance \/ DropReply \/ Restart \/ (\E i \in Ids : Provider(i))
(* Liveness assumes a stable final target and eventual API visibility, provisioning, and tunnel progress. *)
Fairness == /\ WF_vars(Work)
/\ SF_vars(Advance)
/\ \A i \in Ids : /\ WF_vars(Provision(i)) /\ WF_vars(Expose(i))
/\ WF_vars(Finish(i)) /\ WF_vars(Purge(i))
/\ WF_vars(Forget(i)) /\ WF_vars(ApplyRoute(i))
/\ WF_vars(Establish(i))
Spec == Init /\ [][Next]_vars /\ Fairness
TypeOK == /\ objects \in [Ids -> [life : Lives, wan : WANs, route : VIPs]]
/\ visible \subseteq Ids /\ seen \subseteq Ids
/\ tokens \in [Keys -> (Ids \cup {0})] /\ invalid \subseteq Keys
/\ issued \subseteq (Keys \X Ids) /\ nextId \in 1..4
/\ epoch \in 0..LastEpoch /\ phase \in Phases
/\ selected \in Ids \cup {0} /\ reply \in Ids \cup {0}
/\ attempt \in Attempts /\ routeSeen \in VIPs
/\ pending \in [Ids -> VIPs \cup {"None"}]
/\ health \subseteq Ids /\ admitted \subseteq Ids
/\ todo \subseteq Ids /\ refs \subseteq Ids
/\ published \in [epoch : 0..3, id : Ids \cup {0}, route : VIPs]
/\ dropped \in BOOLEAN /\ restarted \in BOOLEAN /\ badPublish \in BOOLEAN
(* OCI Retry Token guarantees expire after 24 hours; expiry is outside this projection. *)
(* https://docs.oracle.com/en-us/iaas/Content/API/Concepts/usingapi.htm *)
OCIRetry == \A a, b \in issued : a[1] = b[1] => a[2] = b[2]
(* DeleteCpe requires the CPE to be disconnected from its DRG. *)
(* https://docs.oracle.com/en-us/iaas/tools/python/latest/api/core/client/oci.core.VirtualNetworkClient.html#oci.core.VirtualNetworkClient.delete_cpe *)
OCIDelete == \A i \in refs : objects[i].life \notin {"Terminating", "Terminated", "Absent"}
OCITokens == \A k \in invalid : tokens[k] # 0
RoutePublish == ~badPublish
Admission == phase = "publish" => selected \in admitted
Recovery == <>[](epoch = LastEpoch /\ Converged)
=============================================================================

146
docs/spec/tier-s/Lease.tla Normal file
View file

@ -0,0 +1,146 @@
---- MODULE Lease ----
EXTENDS Naturals
\* Equal clocks and urgent local steps project the bounded synthetic child fixture.
\* The invariant counts live processes; it makes no claim about kernel SA cleanup.
CONSTANTS LeaseSpan, ReplyMax
ASSUME LeaseSpan \in Nat \ {0} /\ ReplyMax \in 0..20
Retry == 5
Renew == 20
StopWait == 10
PollLow == 5
PollHigh == 11
Limit == LeaseSpan + 2 * PollHigh + ReplyMax + Retry + Renew + StopWait
VARIABLES now, version, seen, age, committed, leader, remaining,
signalled, oldAlive, standby, pollLeft, newAlive
vars == <<now, version, seen, age, committed, leader, remaining,
signalled, oldAlive, standby, pollLeft, newAlive>>
TypeOK ==
/\ now \in 0..Limit
/\ version \in 0..2 /\ seen \in 0..2 /\ age \in 0..LeaseSpan
/\ leader \in {"Pending", "Retry", "Renew", "Stopping", "Done"}
/\ standby \in {"Poll", "Check", "Acquired", "Callback", "Running"}
/\ remaining \in 0..Renew /\ pollLeft \in 0..PollHigh
/\ \A value \in {committed, signalled, oldAlive, newAlive} : value \in BOOLEAN
\* The incumbent is running; one final renewal commits before later requests fail.
Init ==
/\ now = 0 /\ version = 0 /\ seen = 0 /\ age = 0
/\ committed = FALSE /\ leader = "Pending" /\ remaining = 0
/\ signalled = FALSE /\ oldAlive = TRUE
/\ standby = "Poll" /\ pollLeft = 0 /\ newAlive = FALSE
Commit ==
/\ ~committed
/\ committed' = TRUE /\ version' = 1
/\ UNCHANGED <<now, seen, age, leader, remaining, signalled, oldAlive,
standby, pollLeft, newAlive>>
\* RenewDeadline bounds this successful response; the next retry starts afterward.
Reply ==
/\ committed /\ leader = "Pending" /\ now <= ReplyMax
/\ leader' = "Retry" /\ remaining' = Retry
/\ UNCHANGED <<now, version, seen, age, committed, signalled, oldAlive,
standby, pollLeft, newAlive>>
BeginRenew ==
/\ leader = "Retry" /\ remaining = 0
/\ leader' = "Renew" /\ remaining' = Renew
/\ UNCHANGED <<now, version, seen, age, committed, signalled, oldAlive,
standby, pollLeft, newAlive>>
Cancel ==
/\ leader = "Renew" /\ remaining = 0
/\ leader' = "Stopping" /\ remaining' = StopWait
/\ UNCHANGED <<now, version, seen, age, committed, signalled, oldAlive,
standby, pollLeft, newAlive>>
Signal ==
/\ leader = "Stopping" /\ ~signalled
/\ signalled' = TRUE
/\ UNCHANGED <<now, version, seen, age, committed, leader, remaining,
oldAlive, standby, pollLeft, newAlive>>
Reap ==
/\ leader = "Stopping" /\ signalled /\ oldAlive
/\ oldAlive' = FALSE
/\ UNCHANGED <<now, version, seen, age, committed, leader, remaining,
signalled, standby, pollLeft, newAlive>>
Return ==
/\ leader = "Stopping" /\ ~oldAlive
/\ leader' = "Done" /\ remaining' = 0
/\ UNCHANGED <<now, version, seen, age, committed, signalled, oldAlive,
standby, pollLeft, newAlive>>
\* An unchanged Lease does not reset the contender's local observation age.
Observe ==
/\ standby = "Poll" /\ pollLeft = 0
/\ age' = IF seen = version THEN age ELSE 0
/\ seen' = version /\ standby' = "Check"
/\ UNCHANGED <<now, version, committed, leader, remaining,
signalled, oldAlive, pollLeft, newAlive>>
Defer ==
/\ standby = "Check" /\ (age < LeaseSpan \/ seen /= version)
/\ standby' = "Poll" /\ pollLeft' \in PollLow..PollHigh
/\ UNCHANGED <<now, version, seen, age, committed, leader, remaining,
signalled, oldAlive, newAlive>>
Acquire ==
/\ standby = "Check" /\ age = LeaseSpan /\ seen = version
/\ version' = 2 /\ seen' = 2 /\ age' = 0
/\ standby' = "Acquired"
/\ UNCHANGED <<now, committed, leader, remaining,
signalled, oldAlive, pollLeft, newAlive>>
Start ==
/\ standby = "Acquired"
/\ standby' = "Callback"
/\ UNCHANGED <<now, version, seen, age, committed, leader, remaining,
signalled, oldAlive, pollLeft, newAlive>>
Spawn ==
/\ standby = "Callback"
/\ standby' = "Running" /\ newAlive' = TRUE
/\ UNCHANGED <<now, version, seen, age, committed, leader, remaining,
signalled, oldAlive, pollLeft>>
Done == leader = "Done" /\ standby = "Running"
\* Deadlines and local callbacks run before the next one-second clock step.
Urgent ==
\/ ~committed
\/ (leader = "Pending" /\ now = ReplyMax)
\/ (leader \in {"Retry", "Renew"} /\ remaining = 0)
\/ (leader = "Stopping" /\ (~signalled \/ ~oldAlive \/ remaining = 0))
\/ (standby = "Poll" /\ pollLeft = 0)
\/ standby \in {"Check", "Acquired", "Callback"}
Tick ==
/\ ~Done /\ ~Urgent
/\ now' = now + 1
/\ remaining' = IF leader \in {"Retry", "Renew", "Stopping"}
THEN remaining - 1 ELSE remaining
/\ age' = IF standby = "Poll" /\ age < LeaseSpan THEN age + 1 ELSE age
/\ pollLeft' = IF standby = "Poll" THEN pollLeft - 1 ELSE pollLeft
/\ UNCHANGED <<version, seen, committed, leader, signalled,
oldAlive, standby, newAlive>>
Next == Commit \/ Reply \/ BeginRenew \/ Cancel \/ Signal \/ Reap \/ Return
\/ Observe \/ Defer \/ Acquire \/ Start \/ Spawn \/ Tick
\/ (Done /\ UNCHANGED vars)
Spec ==
/\ Init /\ [][Next]_vars
/\ WF_vars(Commit) /\ WF_vars(Reply) /\ WF_vars(BeginRenew)
/\ WF_vars(Cancel) /\ WF_vars(Signal) /\ WF_vars(Reap) /\ WF_vars(Return)
/\ WF_vars(Observe) /\ WF_vars(Defer) /\ WF_vars(Acquire)
/\ WF_vars(Start) /\ WF_vars(Spawn) /\ WF_vars(Tick)
ProcessExclusion == ~(oldAlive /\ newAlive)
Handoff == <>Done
====

View file

@ -0,0 +1,141 @@
---- MODULE Runtime ----
EXTENDS Naturals, FiniteSets
\* Incumbent-owner projection of e063bc9 run.go/parameters.yaml, after successful setup and claim.
\* Probe/endpoint convergence is asynchronous; shutdown here is graceful, unlike Lease.tla.
CONSTANTS Fixed, PublishUnready, Scenario
ASSUME Fixed \in BOOLEAN /\ PublishUnready \in BOOLEAN /\ Scenario \in {"health", "ports", "proxy", "outage"}
Heads == {0, 1}
None == 2
VARIABLES stage, daemon, configured, label, sas, sample, route, flag,
observedHealthy, reported, podReady, endpoint, proxy,
ports, appliedPorts, portRestart, lost, reachable
vars == <<stage, daemon, configured, label, sas, sample, route, flag,
observedHealthy, reported, podReady, endpoint, proxy,
ports, appliedPorts, portRestart, lost, reachable>>
TypeOK ==
/\ stage \in {"Load", "Scan", "Route", "Report", "Idle", "Stop"}
/\ sas \subseteq Heads /\ sample \subseteq Heads
/\ route \in Heads \cup {None}
/\ ports \in 0..1 /\ appliedPorts \in 0..1
/\ \A value \in {daemon, configured, label, flag, observedHealthy,
reported, podReady, endpoint, proxy, portRestart, lost, reachable} : value \in BOOLEAN
Init ==
/\ stage = "Load" /\ daemon = FALSE /\ configured = FALSE /\ label = FALSE
/\ sas = {} /\ sample = {} /\ route = None /\ flag = FALSE
/\ observedHealthy = FALSE /\ reported = FALSE
/\ podReady = FALSE /\ endpoint = FALSE /\ proxy = TRUE
/\ ports = 0 /\ appliedPorts = 0 /\ portRestart = FALSE /\ lost = FALSE /\ reachable = TRUE
Load ==
/\ stage = "Load"
/\ daemon' = TRUE /\ configured' = TRUE /\ label' = TRUE
/\ stage' = "Scan" /\ appliedPorts' = ports /\ flag' = FALSE
/\ UNCHANGED <<sas, sample, route, observedHealthy, reported, podReady,
endpoint, proxy, ports, portRestart, lost, reachable>>
Scan ==
/\ stage = "Scan" /\ daemon
/\ sample' = sas /\ stage' = "Route"
/\ UNCHANGED <<daemon, configured, label, sas, route, flag, observedHealthy,
reported, podReady, endpoint, proxy, ports, appliedPorts, portRestart, lost, reachable>>
Route ==
/\ stage = "Route"
/\ route' = IF sample = {} THEN route ELSE IF 0 \in sample THEN 0 ELSE 1
/\ stage' = "Report"
/\ UNCHANGED <<daemon, configured, label, sas, sample, flag, observedHealthy,
reported, podReady, endpoint, proxy, ports, appliedPorts, portRestart, lost, reachable>>
Report ==
/\ stage = "Report"
/\ flag' = IF Fixed THEN sample /= {} ELSE TRUE
/\ observedHealthy' = (sample /= {} /\ route \in sample)
/\ reported' = TRUE /\ stage' = "Idle"
/\ UNCHANGED <<daemon, configured, label, sas, sample, route, podReady,
endpoint, proxy, ports, appliedPorts, portRestart, lost, reachable>>
Poll ==
/\ stage = "Idle" /\ ports = appliedPorts
/\ stage' = "Scan"
/\ UNCHANGED <<daemon, configured, label, sas, sample, route, flag, observedHealthy,
reported, podReady, endpoint, proxy, ports, appliedPorts, portRestart, lost, reachable>>
ChangePorts ==
/\ Scenario = "ports" /\ ports = 0 /\ stage = "Idle" /\ daemon
/\ sas /= {} /\ route \in sas
/\ ports' = 1
/\ UNCHANGED <<stage, daemon, configured, label, sas, sample, route, flag,
observedHealthy, reported, podReady, endpoint, proxy, appliedPorts,
portRestart, lost, reachable>>
Reload ==
/\ stage = "Idle" /\ ports /= appliedPorts
/\ stage' = IF Fixed THEN "Scan" ELSE "Stop"
/\ appliedPorts' = IF Fixed THEN ports ELSE appliedPorts
/\ UNCHANGED <<daemon, configured, label, sas, sample, route, flag, observedHealthy,
reported, podReady, endpoint, proxy, ports, portRestart, lost, reachable>>
Stop ==
/\ stage = "Stop"
/\ daemon' = FALSE /\ sas' = {} /\ flag' = FALSE /\ stage' = "Load"
/\ portRestart' = (portRestart \/ (daemon /\ ports /= appliedPorts))
/\ UNCHANGED <<configured, label, sample, route, observedHealthy, reported,
podReady, endpoint, proxy, ports, appliedPorts, lost, reachable>>
Probe ==
LET desired == configured /\ flag /\ (Fixed \/ proxy)
IN /\ podReady /= desired /\ podReady' = desired
/\ UNCHANGED <<stage, daemon, configured, label, sas, sample, route, flag,
observedHealthy, reported, endpoint, proxy, ports, appliedPorts,
portRestart, lost, reachable>>
\* Publishing the active endpoint before serving readiness breaks the initial IKE dependency cycle.
Realize ==
LET desired == label /\ (PublishUnready \/ podReady)
IN /\ endpoint /= desired /\ endpoint' = desired
/\ UNCHANGED <<stage, daemon, configured, label, sas, sample, route, flag,
observedHealthy, reported, podReady, proxy, ports, appliedPorts,
portRestart, lost, reachable>>
Negotiate ==
/\ daemon /\ configured /\ endpoint /\ reachable /\ sas /= Heads
/\ sas' \in SUBSET Heads /\ sas \subseteq sas' /\ sas' /= sas
/\ UNCHANGED <<stage, daemon, configured, label, sample, route, flag, observedHealthy,
reported, podReady, endpoint, proxy, ports, appliedPorts, portRestart, lost, reachable>>
LosePeers ==
/\ ~lost /\ sas = Heads
/\ IF Scenario = "outage" THEN sas' = {} ELSE sas' \in (SUBSET Heads) \ {Heads}
/\ lost' = TRUE
/\ reachable' = (Scenario /= "outage")
/\ UNCHANGED <<stage, daemon, configured, label, sample, route, flag, observedHealthy,
reported, podReady, endpoint, proxy, ports, appliedPorts, portRestart>>
ProxyFails ==
/\ Scenario = "proxy" /\ proxy /\ podReady /\ endpoint
/\ sas /= {} /\ route \in sas
/\ proxy' = FALSE
/\ UNCHANGED <<stage, daemon, configured, label, sas, sample, route, flag,
observedHealthy, reported, podReady, endpoint, ports, appliedPorts,
portRestart, lost, reachable>>
Next == Load \/ Scan \/ Route \/ Report \/ Poll \/ ChangePorts \/ Reload \/ Stop
\/ Probe \/ Realize \/ Negotiate \/ LosePeers \/ ProxyFails
Spec == Init /\ [][Next]_vars
/\ WF_vars(Load) /\ WF_vars(Scan) /\ WF_vars(Route) /\ WF_vars(Report)
/\ WF_vars(Poll) /\ WF_vars(Reload) /\ WF_vars(Stop)
/\ WF_vars(Probe) /\ WF_vars(Realize) /\ WF_vars(Negotiate)
/\ SF_vars(ChangePorts) /\ SF_vars(ProxyFails) /\ SF_vars(LosePeers)
HealthyObservation == reported => (~flag \/ observedHealthy)
PortContinuity == ~portRestart
TransportRecovery == <>[]endpoint
Usable == daemon /\ endpoint /\ sas /= {} /\ route \in sas /\ ports = appliedPorts
ServingRecovery == (<>[]reachable) => <>[]Usable
LossReported == (<>[]~reachable) => <>[](~flag /\ ~podReady)
====

View file

@ -0,0 +1,10 @@
CONSTANTS
Mode = "Fixed"
Scenario = "Retry"
ResourceKind = "VPN"
LoseReply = TRUE
RestartOnce = TRUE
DelayLists = TRUE
SPECIFICATION Spec
INVARIANTS TypeOK OCIRetry OCIDelete OCITokens Admission RoutePublish
PROPERTY Recovery

View file

@ -0,0 +1,10 @@
CONSTANTS
Mode = "Fixed"
Scenario = "Retry"
ResourceKind = "CPE"
LoseReply = TRUE
RestartOnce = TRUE
DelayLists = TRUE
SPECIFICATION Spec
INVARIANTS TypeOK OCIRetry OCIDelete OCITokens Admission RoutePublish
PROPERTY Recovery

View file

@ -0,0 +1,10 @@
CONSTANTS
Mode = "Current"
Scenario = "Retry"
ResourceKind = "CPE"
LoseReply = FALSE
RestartOnce = FALSE
DelayLists = FALSE
SPECIFICATION Spec
INVARIANTS TypeOK OCIRetry OCIDelete OCITokens Admission
PROPERTY Recovery

View file

@ -0,0 +1,10 @@
CONSTANTS
Mode = "Fixed"
Scenario = "Routes"
ResourceKind = "VPN"
LoseReply = TRUE
RestartOnce = TRUE
DelayLists = TRUE
SPECIFICATION Spec
INVARIANTS TypeOK OCIRetry OCIDelete OCITokens Admission RoutePublish
PROPERTY Recovery

View file

@ -0,0 +1,10 @@
CONSTANTS
Mode = "Fixed"
Scenario = "Retry"
ResourceKind = "CPE"
LoseReply = FALSE
RestartOnce = FALSE
DelayLists = FALSE
SPECIFICATION Spec
INVARIANTS TypeOK OCIRetry OCIDelete OCITokens Admission RoutePublish
PROPERTY Recovery

View file

@ -0,0 +1,10 @@
CONSTANTS
Mode = "Current"
Scenario = "Routes"
ResourceKind = "VPN"
LoseReply = FALSE
RestartOnce = FALSE
DelayLists = FALSE
SPECIFICATION Spec
INVARIANTS TypeOK OCIRetry OCIDelete OCITokens Admission RoutePublish
PROPERTY Recovery

View file

@ -0,0 +1,10 @@
CONSTANTS
Mode = "Fixed"
Scenario = "Routes"
ResourceKind = "VPN"
LoseReply = FALSE
RestartOnce = FALSE
DelayLists = FALSE
SPECIFICATION Spec
INVARIANTS TypeOK OCIRetry OCIDelete OCITokens Admission RoutePublish
PROPERTY Recovery

View file

@ -0,0 +1,10 @@
CONSTANTS
Mode = "Current"
Scenario = "Retry"
ResourceKind = "VPN"
LoseReply = FALSE
RestartOnce = FALSE
DelayLists = FALSE
SPECIFICATION Spec
INVARIANTS TypeOK OCIRetry OCIDelete OCITokens Admission RoutePublish
PROPERTY Recovery

View file

@ -0,0 +1,3 @@
CONSTANTS Fixed = FALSE PublishUnready = FALSE Scenario = "health"
SPECIFICATION Spec
INVARIANTS TypeOK HealthyObservation

View file

@ -0,0 +1,3 @@
CONSTANTS Fixed = FALSE PublishUnready = FALSE Scenario = "ports"
SPECIFICATION Spec
INVARIANTS TypeOK PortContinuity

View file

@ -0,0 +1,4 @@
CONSTANTS Fixed = FALSE PublishUnready = FALSE Scenario = "proxy"
SPECIFICATION Spec
INVARIANT TypeOK
PROPERTY TransportRecovery

View file

@ -0,0 +1,4 @@
CONSTANTS LeaseSpan = 30 ReplyMax = 0
SPECIFICATION Spec
INVARIANTS TypeOK ProcessExclusion
PROPERTY Handoff

View file

@ -0,0 +1,4 @@
CONSTANTS LeaseSpan = 60 ReplyMax = 20
SPECIFICATION Spec
INVARIANTS TypeOK ProcessExclusion
PROPERTY Handoff

View file

@ -0,0 +1,4 @@
CONSTANTS LeaseSpan = 40 ReplyMax = 20
SPECIFICATION Spec
INVARIANTS TypeOK ProcessExclusion
PROPERTY Handoff

View file

@ -0,0 +1,4 @@
CONSTANTS Fixed = TRUE PublishUnready = FALSE Scenario = "health"
SPECIFICATION Spec
INVARIANTS TypeOK HealthyObservation PortContinuity
PROPERTY ServingRecovery

View file

@ -0,0 +1,4 @@
CONSTANTS Fixed = TRUE PublishUnready = TRUE Scenario = "health"
SPECIFICATION Spec
INVARIANTS TypeOK HealthyObservation PortContinuity
PROPERTIES TransportRecovery ServingRecovery LossReported

View file

@ -0,0 +1,4 @@
CONSTANTS Fixed = TRUE PublishUnready = TRUE Scenario = "outage"
SPECIFICATION Spec
INVARIANTS TypeOK HealthyObservation PortContinuity
PROPERTIES TransportRecovery ServingRecovery LossReported

Some files were not shown because too many files have changed in this diff Show more