Commit 5dd01e92 authored by Christos Tranoris's avatar Christos Tranoris
Browse files

update diagram

parent f341f0ba
Loading
Loading
Loading
Loading
+6 −0
Changes for .changelog/20261001_1230_architecture-diagram-two-paths.md: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
# Architecture diagram: two request paths and tentative planning inventory

Redrew the §2 architecture diagram in `docs/writing-an-openslice-controller.md`: production path
(blue, solid) and planning path (orange, dashed) are now visually distinct, with a comparison table.
Highlights that a planning callback is stored in OSOM's internal tentative planning inventory, never
the production inventory. The planning sequence diagram gained the same participant.
+1 −0
Changes for .changelog/index.md: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

| Doc | Description |
|---|---|
| [20261001_1230_architecture-diagram-two-paths.md](20261001_1230_architecture-diagram-two-paths.md) | Redrew the guide's architecture diagram to separate the production and planning paths, and to show that planning callbacks land in the internal tentative planning inventory. |
| [20261001_1200_move-docs-to-changelog.md](20261001_1200_move-docs-to-changelog.md) | Moved change docs from `docs/` to `.changelog/`; `docs/` keeps only `writing-an-openslice-controller.md`, and the README now points to it. |
| [20260901_1155_kubernetescluster-estimate-scales-with-nodecount.md](20260901_1155_kubernetescluster-estimate-scales-with-nodecount.md) | `KubernetesCluster.estimateProfile` now scales with the requested `nodeCount`: a fixed control-plane part plus a per-node increment, calibrated so the default 3-node cluster reproduces the spec's original flat profile. Reads `nodeCount` from the request (not the singleton's mutable field, which the background OPERATION callback would race on), following the `RadioEngineer` pattern; falls back to 3 nodes when the characteristic is absent, unparseable, or outside `1..500`. New `KubernetesClusterTest` (6 tests); suite 22/22 on the estimator group. |
| [20260827_1600_do-not-release-an-allocation-you-did-not-make.md](20260827_1600_do-not-release-an-allocation-you-did-not-make.md) | The X.731 pass this morning left `setResourceStatus(AVAILABLE)` standing in all ten specs, on the reasoning that `resourceStatus` no longer decides anything. It does not decide the service state, but it is how the platform records **pool allocation** — and OSOM builds the outbound `ResourceUpdate` from the live catalog entry, so that line overwrote an orchestrator's `RESERVED` and returned a pooled resource to the free pool while an order was using it, where a second order can take it and the end-of-operating-date sweep can terminate it. A reference project was teaching every controller author to do it. All ten specs now call the platform's new `declareResourceStatus`, which applies a verdict over a condition or over nothing and leaves a `RESERVED`/`STANDBY` alone; the three health attributes are still set unconditionally, because health is the controller's own to state. Teardown still clears the allocation outright. `ResourceA`/`ResourceB` carry the full explanation as the specs an author reads first. Adds three tests run against every spec in the catalogue; suite 123/123. |
+43 −17
Changes for docs/writing-an-openslice-controller.md: 43 added lines, 17 removed lines.
Original line number Diff line number Diff line
@@ -49,37 +49,61 @@ convention here is the same as a Java package.
## 2. Architecture

```mermaid
flowchart TB
flowchart LR
    subgraph OSL["OpenSlice"]
        OSOM["OSOM<br/>orchestrator / planner"]
        TMF["TMF API<br/>catalog + inventory"]
        INV[("TMF Inventory<br/><b>production</b> resources")]
        TINV[("<b>Tentative planning inventory</b><br/>internal, per-plan resources")]
        CATS["TMF Catalog"]
    end

    BUS{{"ActiveMQ Artemis"}}

    subgraph CTRL["This controller"]
        ROUTES["PartnerRouteBuillder<br/><i>Camel routes, JSON unmarshal</i>"]
        REPO["ResourceRepoService<br/><i>production vs planning</i>"]
        REG["ResourceSpecRegistry<br/><i>the catalogue</i>"]
        SPECS["ExampleResourceSpec<br/><i>VirtualMachine, RadioNode, ...</i>"]
        EST["ResourceEstimator<br/><i>cost model</i>"]
        BOOT["BootstrapService"]
        REPO{"ResourceRepoService<br/><i>X-OSL-SIMULATION?</i>"}
        REG["ResourceSpecRegistry<br/>+ ExampleResourceSpec"]
        EST["ResourceEstimator<br/><i>planning only</i>"]
        CAT["CatalogClient"]
        BOOT["BootstrapService"]
    end

    OSOM -->|"CREATE/UPDATE/DELETE<br/>+ /PLANNING variants"| BUS
    BUS --> ROUTES --> REPO
    REPO --> REG --> SPECS
    REPO --> EST
    REPO -->|"planning callback"| BUS
    BUS -->|"PLANNING.RESOURCE.CREATEORUPDATE"| OSOM
    REPO -->|"production only"| CAT
    %% Production path (blue)
    OSOM ==>|"1 CREATE / UPDATE / DELETE"| BUS
    BUS ==> ROUTES ==> REPO
    REPO ==>|"2 real write"| CAT
    CAT ==>|"CATALOG.* queues"| BUS
    BUS ==>|"3 persisted"| INV

    %% Planning path (orange, dashed)
    OSOM -.->|"1 .../PLANNING + X-OSL-SIMULATION"| BUS
    REPO -.->|"2 no side effects:<br/>logic + estimate"| EST
    REPO -.->|"3 PLANNING.RESOURCE.CREATEORUPDATE<br/>(HELD, then UP, + estimates)"| BUS
    BUS -.->|"4 tentative resource stored"| TINV
    TINV -.->|"plan + costs"| OSOM

    REPO --- REG
    BOOT --> REG
    BOOT --> CAT
    CAT -->|"CATALOG.* queues"| BUS
    BUS --> TMF
    BUS --- CATS

    linkStyle 0,1,2,3,4,5 stroke:#1f6feb,stroke-width:3px
    linkStyle 6,7,8,9,10 stroke:#e8590c,stroke-width:2px,stroke-dasharray:6 4
    style TINV fill:#fff4e6,stroke:#e8590c,stroke-width:3px,color:#000
    style INV fill:#e7f0ff,stroke:#1f6feb,stroke-width:2px,color:#000
```

| Path | Blue, solid — **production** | Orange, dashed — **planning** |
|---|---|---|
| Queue | `CREATE/UPDATE/DELETE/<category>/<version>` | same, with `/PLANNING` suffix |
| Controller | writes the real resource via `CatalogClient` | runs the logic, **no side effects**, adds estimates |
| Result lands in | TMF **production inventory** | OSOM's internal **tentative planning inventory** |

> **A planning callback never touches the production inventory.** The resource the controller reports on
> `PLANNING.RESOURCE.CREATEORUPDATE` is stored by OSOM in an internal *tentative planning inventory*,
> scoped to the plan being evaluated. If the order is never placed, that tentative resource is simply
> discarded — nothing real was created.

### The pieces

| Class | Responsibility |
@@ -158,6 +182,7 @@ sequenceDiagram
    participant C as ResourceRepoService
    participant S as spec.resourceLogic()
    participant CB as PLANNING.RESOURCE.CREATEORUPDATE
    participant TI as "Tentative planning inventory"

    OSOM->>Q: ResourceCreate + X-OSL-SIMULATION<br/>+ org.etsi.osl.operationDurationSeconds
    Q->>C: createResource(headers, body)
@@ -167,7 +192,8 @@ sequenceDiagram
    CB-->>C: acknowledged resource id
    Note over C: a moment later, background thread
    C->>CB: AVAILABLE + UP + estimate.operation.*
    CB-->>OSOM: HELD → UP observed,<br/>plan converges with costs attached
    CB->>TI: store tentative resource (HELD → UP)
    TI-->>OSOM: plan converges with costs attached
```

Three things are going on there, and each is a rule worth copying.