Skip to content

scrimlet-reconcilers status (PR 3/3): add omdb command and bootstrap-lockstep API to display status - #11058

Open
jgallagher wants to merge 10 commits into
mainfrom
john/scrimlet-reconcilers-status
Open

scrimlet-reconcilers status (PR 3/3): add omdb command and bootstrap-lockstep API to display status#11058
jgallagher wants to merge 10 commits into
mainfrom
john/scrimlet-reconcilers-status

Conversation

@jgallagher

Copy link
Copy Markdown
Contributor

This PR is a lot smaller than it looks: ~2400 lines are changes to the lockstep API document, and another ~800 lines are Display impls inside omdb. The Display impls are worth a quick review but aren't load bearing; I'll put example output from a racklette in a comment below.

@jgallagher

Copy link
Copy Markdown
Contributor Author

This command requires specifying the bootstrap address of a sled-agent; the easiest thing to do from a switch zone is to ask your own sled-agent, for multiple reasons:

  1. It's easy to find its IP (look at your bootstrap IP; change the ::2 to ::1)
  2. This is a lockstep API, and omdb is guaranteed to be in sync with its own sled's switch zone
  3. The status is only meaningful for scrimlets; you could ask both scrimlets from one switch zone or each scrimlet from its own switch zone. The latter would be required if the scrimlets were on different OS versions (e.g., partway through a live update) and there were changes to this lockstep API.

This branch deployed on berlin asking for our own scrimlet's status:

[berlin]root@oxz_switch1:~# ipadm | grep bootstrap
oxBootstrap0/bootstrap6 static ok       fdb0:a840:2504:190::2/64
[berlin]root@oxz_switch1:~# omdb sled-agent --bootstrap-lockstep-url http://[fdb0:a840:2504:190::1]:8080 network-config reconciler-status
dpd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 19
        completed at 2026-08-11T18:05:00.372Z
        ran for 8.92463ms
        detailed status:
            port settings:
                reconciliation completed
                    ports unchanged: qsfp0
                    clear failures: none
                    apply failures: none
            NAT:
                reconciliation completed
                    zones unchanged: 0f952f1f-6f1d-4ec1-b661-afd8f4804b6f, 29ec2137-f369-431a-83be-76e74f0beee2, 2a4583fa-31b2-4fb6-bb38-c89581ede01c, 9b4bb130-1e4c-43a9-be20-80329fca541d, aa1d5931-2d4b-4187-bb07-2f034e8a5476, b8c9fb9f-8a15-45f5-a480-13a548ac6d61, c1d5420d-5905-4a6f-9464-d125728f43f1, c7cef13a-0ceb-4426-bed2-4130f74a1fa0
                    remove failures: none
                    create failures: none

mgd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 19
        completed at 2026-08-11T18:05:00.335Z
        ran for 2.437648ms
        detailed status:
            static routes:
                reconciliation completed
                    routes unchanged: 0
                    v4 routes deleted / added: 0 / 0
                    v6 routes deleted / added: 0 / 0
            BGP:
                reconciliation completed
                    did change max paths: false
                    routers created / updated / deleted: 0 / 0 / 0
                    origin4 created / updated / deleted: 0 / 0 / 0
                    origin6 created / updated / deleted: 0 / 0 / 0
                    shapers created / updated / deleted: 0 / 0 / 0
                    checkers created / updated / deleted: 0 / 0 / 0
                    numbered peers created / updated / deleted: 0 / 0 / 0
                    unnumbered peers created / updated / deleted: 0 / 0 / 0
                    errors: none
            BFD:
                reconciliation completed
                    remove failures: none
                    add failures: none

lldpd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 19
        completed at 2026-08-11T18:05:00.327Z
        ran for 2.027222ms
        detailed status:
            reconciliation skipped: config is up to date

uplinkd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 19
        completed at 2026-08-11T18:05:00.324Z
        ran for 1.11622ms
        detailed status:
            reconciliation skipped: config is up to date

Asking for the other scrimlet's status is fine too, after finding its IP:

[berlin]root@oxz_switch1:~# pilot host exec -c 'ipadm | grep bootstrap6' 14
14  BRM42220011        ok: bootstrap0/bootstrap6 static ok         fdb0:a840:2504:211::1/64
[berlin]root@oxz_switch1:~# omdb sled-agent --bootstrap-lockstep-url http://[fdb0:a840:2504:211::1]:8080 network-config reconciler-status
dpd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 28
        completed at 2026-08-11T18:07:30.441Z
        ran for 9.2019ms
        detailed status:
            port settings:
                reconciliation completed
                    ports unchanged: qsfp0
                    clear failures: none
                    apply failures: none
            NAT:
                reconciliation completed
                    zones unchanged: 0f952f1f-6f1d-4ec1-b661-afd8f4804b6f, 29ec2137-f369-431a-83be-76e74f0beee2, 2a4583fa-31b2-4fb6-bb38-c89581ede01c, 9b4bb130-1e4c-43a9-be20-80329fca541d, aa1d5931-2d4b-4187-bb07-2f034e8a5476, b8c9fb9f-8a15-45f5-a480-13a548ac6d61, c1d5420d-5905-4a6f-9464-d125728f43f1, c7cef13a-0ceb-4426-bed2-4130f74a1fa0
                    remove failures: none
                    create failures: none

mgd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 28
        completed at 2026-08-11T18:07:30.370Z
        ran for 3.556892ms
        detailed status:
            static routes:
                reconciliation completed
                    routes unchanged: 0
                    v4 routes deleted / added: 0 / 0
                    v6 routes deleted / added: 0 / 0
            BGP:
                reconciliation completed
                    did change max paths: false
                    routers created / updated / deleted: 0 / 0 / 0
                    origin4 created / updated / deleted: 0 / 0 / 0
                    origin6 created / updated / deleted: 0 / 0 / 0
                    shapers created / updated / deleted: 0 / 0 / 0
                    checkers created / updated / deleted: 0 / 0 / 0
                    numbered peers created / updated / deleted: 0 / 0 / 0
                    unnumbered peers created / updated / deleted: 0 / 0 / 0
                    errors: none
            BFD:
                reconciliation completed
                    remove failures: none
                    add failures: none

lldpd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 28
        completed at 2026-08-11T18:07:30.353Z
        ran for 1.393313ms
        detailed status:
            reconciliation skipped: config is up to date

uplinkd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 28
        completed at 2026-08-11T18:07:30.346Z
        ran for 860.717µs
        detailed status:
            reconciliation skipped: config is up to date

Asking for the status from a non-scrimlet sled "works" but there's nothing interesting there:

[berlin]root@oxz_switch1:~# pilot host exec -c 'ipadm | grep bootstrap6' 15
15  BRM44220007        ok: bootstrap0/bootstrap6 static ok         fdb0:a840:2504:492::1/64
[berlin]root@oxz_switch1:~# omdb sled-agent --bootstrap-lockstep-url http://[fdb0:a840:2504:492::1]:8080 network-config reconciler-status
not running: no switch detected

@jgallagher
jgallagher force-pushed the john/collapse-enum-variants branch from c7d7161 to e407b6d Compare August 12, 2026 15:14
Base automatically changed from john/collapse-enum-variants to main August 12, 2026 17:21
@jgallagher
jgallagher force-pushed the john/scrimlet-reconcilers-status branch from af9ea45 to 8b5c9db Compare August 12, 2026 17:26
Comment thread dev-tools/omdb/src/bin/omdb/sled_agent/reconciler_status.rs Outdated
ScrimletReconcilersStatus::WaitingForSledAgentNetworkingInfo => {
write!(
f,
"not running: sled-agent has not yet initialized \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be not yet running if we're still waiting?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily; we may never start running (e.g., if we're not a scrimlet).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then how about changing the sled-agent has not yet initialized bit then? It implies that it will start running eventually no?

Comment on lines +175 to +184
if let Some(last_completion) = last_completion {
writeln!(f, "last completion:")?;
writeln!(
IndentWriter::new(INDENT, f),
"{}",
ReconciliationCompletedStatusDisplay(&last_completion)
)?;
} else {
writeln!(f, "last completion: none")?;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (take it or leave it): It'd be nice if the "none" had the same indentation as when there is a last_completion

last completion:
    none

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love this because it makes the overall output vertically longer (and it's already annoying to have to scroll to see it all). There are several other places that have a something: none that would also bump up the vertical space if we applied this everywhere.

Comment thread dev-tools/omdb/src/bin/omdb/sled_agent/reconciler_status.rs Outdated
Comment thread dev-tools/omdb/src/bin/omdb/sled_agent/reconciler_status.rs Outdated
Comment thread dev-tools/omdb/src/bin/omdb/sled_agent/reconciler_status.rs
Comment on lines +761 to +762
"{name} created / updated / deleted: \
{created} / {updated} / {deleted}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be a little easier to read something like:

routers:
    created: 0
    updated: 0
    deleted: 0

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this will really blow up the vertical space too; BGP has a ton of counters to report. I could special case "all zero" and make it either

routers: unchanged

or break out counters by line if any of them are nonzero? That might be the best way to go - it simplifies the output in the common case (nothing changed) while breaking out the counters if there's anything interesting?

{
writeln!(
f,
"v4 routes deleted / added: {deleted} / {added}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, how about:

v4 routes:
    deleted: 0
    added: 0

"format": "uuid"
},
"RackInitializeRequest": {
"description": "Configuration for the \"rack setup service\".\n\nThe Rack Setup Service should be responsible for one-time setup actions, such as CockroachDB placement and initialization. Without operator intervention, however, these actions need a way to be automated in our deployment.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We most often refer to it as RSS, so it'd be nice to have that here so people new to the codebase make the connection

Suggested change
"description": "Configuration for the \"rack setup service\".\n\nThe Rack Setup Service should be responsible for one-time setup actions, such as CockroachDB placement and initialization. Without operator intervention, however, these actions need a way to be automated in our deployment.",
"description": "Configuration for the \"rack setup service\".\n\nThe Rack Setup Service (RSS) should be responsible for one-time setup actions, such as CockroachDB placement and initialization. Without operator intervention, however, these actions need a way to be automated in our deployment.",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't necessarily disagree, but this doesn't have anything to do with this PR. 😅 This is coming from a docstring on some RSS-related type I'm not touching.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhhhhh the diff makes it look like this type wasn't in the OpenAPI doc before, but it was. nvm

]
},
{
"description": "`id` will be none if the rack was already initialized on startup.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this description be more explicit about what the object is? Also, this type is a little light on the documentation. It's be nice to have docs on each variant

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as #11058 (comment), this isn't from changes in this PR. I don't think I want to mix in doc cleanup for unrelated types?

@jgallagher

Copy link
Copy Markdown
Contributor Author

@karencfv Thanks for the review - this is ready for a second pass. I took several of your suggestions and left others out; here's example output from a racklette where we see several nonzero values from BGP settings being applied:

dpd reconciler:
    current status:
        idle
    last completion:
        activation reason: first execution on start
        activation count: 0
        completed at: 2026-08-13T19:27:38.420Z
        ran for 22.044274ms
        detailed status:
            port settings:
                reconciliation completed
                    ports applied: qsfp0
                    clear failures: none
                    apply failures: none
            NAT:
                reconciliation completed
                    zones unchanged:
                        * zone c80cddd0-1eaa-438f-bbcb-224493227b13NAT entries removed: none
                    NAT entries created
                        * zone 461c913a-95f8-49b6-94db-80aa386a7f0a: 172.20.37.2 (ports 0-65535)
                        * zone 4bf43ac2-204c-400d-af88-197c21574d62: 172.20.37.10 (ports 0-65535)
                        * zone 69dfb0e2-fbbd-44a9-9e9e-6e7501117423: 172.20.37.7 (ports 0-16383)
                        * zone 947bcf81-ebdc-4c36-8645-75db7bc90e4f: 172.20.37.8 (ports 0-65535)
                        * zone b8c58fb7-aaf4-4284-8223-d15134357afd: 172.20.37.9 (ports 0-65535)
                        * zone eb85fe05-ac82-4cdb-9609-b4947bf369f4: 172.20.37.1 (ports 0-65535)
                        * zone f1462b05-486a-45ae-8949-3604341424dc: 172.20.37.3 (ports 0-65535)remove failures: none
                    create failures: none

mgd reconciler:
    current status:
        idle
    last completion:
        activation reason: first execution on start
        activation count: 0
        completed at: 2026-08-13T19:27:38.421Z
        ran for 22.469966ms
        detailed status:
            static routes:
                reconciliation completed
                    routes unchanged: 0
                    v4 routes: unchanged
                    v6 routes: unchanged
            BGP:
                reconciliation completed
                    did change max paths: true
                    routers:
                        created: 1
                        updated: 0
                        deleted: 0
                    origin4:
                        created: 1
                        updated: 0
                        deleted: 0
                    origin6:
                        created: 1
                        updated: 0
                        deleted: 0
                    shapers: unchanged
                    checkers: unchanged
                    numbered peers:
                        created: 1
                        updated: 0
                        deleted: 0
                    unnumbered peers: unchanged
                    errors: none
            BFD:
                reconciliation completed
                    remove failures: none
                    add failures: none

lldpd reconciler:
    current status:
        idle
    last completion:
        activation reason: first execution on start
        activation count: 0
        completed at: 2026-08-13T19:27:38.426Z
        ran for 27.510555ms
        detailed status:
            successfully reconciled 1 port:
                * qsfp0: Enabled

uplinkd reconciler:
    current status:
        idle
    last completion:
        activation reason: first execution on start
        activation count: 0
        completed at: 2026-08-13T19:27:38.424Z
        ran for 24.704716ms
        detailed status:
            successfully reconciled 1 port:
                * qsfp0_0: 172.20.15.69/29

and here's a steady-state output later when the reconciler has nothing to do, so we collapse the counts down to unchanged:

dpd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 2
        completed at: 2026-08-13T19:28:38.446Z
        ran for 9.624578ms
        detailed status:
            port settings:
                reconciliation completed
                    ports unchanged: qsfp0
                    clear failures: none
                    apply failures: none
            NAT:
                reconciliation completed
                    zones unchanged:
                        * zone 461c913a-95f8-49b6-94db-80aa386a7f0a
                        * zone 4bf43ac2-204c-400d-af88-197c21574d62
                        * zone 69dfb0e2-fbbd-44a9-9e9e-6e7501117423
                        * zone 947bcf81-ebdc-4c36-8645-75db7bc90e4f
                        * zone b8c58fb7-aaf4-4284-8223-d15134357afd
                        * zone c80cddd0-1eaa-438f-bbcb-224493227b13
                        * zone eb85fe05-ac82-4cdb-9609-b4947bf369f4
                        * zone f1462b05-486a-45ae-8949-3604341424dcNAT entries removed: none
                    NAT entries created: none
                    remove failures: none
                    create failures: none

mgd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 2
        completed at: 2026-08-13T19:28:38.440Z
        ran for 3.586878ms
        detailed status:
            static routes:
                reconciliation completed
                    routes unchanged: 0
                    v4 routes: unchanged
                    v6 routes: unchanged
            BGP:
                reconciliation completed
                    did change max paths: false
                    routers: unchanged
                    origin4: unchanged
                    origin6: unchanged
                    shapers: unchanged
                    checkers: unchanged
                    numbered peers: unchanged
                    unnumbered peers: unchanged
                    errors: none
            BFD:
                reconciliation completed
                    remove failures: none
                    add failures: none

lldpd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 2
        completed at: 2026-08-13T19:28:38.432Z
        ran for 1.12246ms
        detailed status:
            reconciliation skipped: config is up to date

uplinkd reconciler:
    current status:
        idle
    last completion:
        activation reason: periodic timer fired
        activation count: 2
        completed at: 2026-08-13T19:28:38.430Z
        ran for 1.214425ms
        detailed status:
            reconciliation skipped: config is up to date

@karencfv karencfv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I've left a couple of questions, but everything else looks great

"format": "uuid"
},
"RackInitializeRequest": {
"description": "Configuration for the \"rack setup service\".\n\nThe Rack Setup Service should be responsible for one-time setup actions, such as CockroachDB placement and initialization. Without operator intervention, however, these actions need a way to be automated in our deployment.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhhhhh the diff makes it look like this type wasn't in the OpenAPI doc before, but it was. nvm

ScrimletReconcilersStatus::WaitingForSledAgentNetworkingInfo => {
write!(
f,
"not running: sled-agent has not yet initialized \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then how about changing the sled-agent has not yet initialized bit then? It implies that it will start running eventually no?

Comment on lines +835 to +847
writeln!(f, "routes unchanged: {unchanged}")?;

if let (&Ok(deleted), &Ok(added)) =
(delete_v4_result, add_v4_result)
{
if deleted == 0 && added == 0 {
writeln!(f, "v4 routes: unchanged")?;
} else {
writeln!(f, "v4 routes:")?;
let mut f = IndentWriter::new(INDENT, &mut f);
writeln!(f, "deleted: {deleted}")?;
writeln!(f, "added: {added}")?;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit is a little confusing to me. In the sample output below it says there are routes unchanged: 0 which I assume means something changed, but then it says all v4 and v6 routes are unchanged. So what changed then?

routes unchanged: 0
v4 routes: unchanged
v6 routes: unchanged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants