Refactor/qod
Async QoD sessions: POST/DELETE /sessions, completion handling, qos-profiles stubs Summary Brings QoD POST/DELETE /qod/v0/sessions in line with the same async pattern used for POST /appinstances: OEG mints its own ids, persists bookkeeping rows, publishes a command.srm.* message, and reacts to event.srm.operation.completed — instead of the previous synchronous SRMClient calls against SRM endpoints that don't actually exist. Also fixes the NBI schemas to match the vendored qod-api.yaml, and adds stub routes for the two QoD operations that had none at all.
What's included:
- CAMARA schema conformance (schemas.py/router.py): renamed to the spec's own names (CreateSession/SessionInfo), fixed the sink→webhook field, added the validators the spec requires (device/applicationServer presence, IPv4 anyOf, qosProfile pattern, ports), declared the documented error responses.
- POST /sessions async: SRMNetworkCapabilityActivateCommand (domain/quality_on_demand.py), build_activate_command mapper, and the service rewrite — mints operation_id/session_id/service_specification_id, persists Operation (PENDING) + a new qod_sessions row (REQUESTED), publishes the activate command, returns 201 built from the request (per the spec's own REQUESTED-status design — no 202 deviation needed).
- qod_sessions persistence: new table/domain model/repo, scoped to async bookkeeping only — not a read cache for GET.
- DELETE /sessions/{id} async: new OperationType.NETWORK_CAPABILITY_DEACTIVATE, SRMNetworkCapabilityDeactivateCommand/build_deactivate_command, service rewrite — resolves external_ref from qod_sessions, 404s if the session is unknown or not yet confirmed (still REQUESTED), publishes the deactivate command keyed on external_ref, returns 204.
- GET /qos-profiles, GET /qos-profiles/{name}: routes added, both return 501 — the catalog itself isn't implemented, but callers now get a proper response instead of a route-not-found 404.
Open points:
-
GET /sessions/{id} no confirmed SRM contract to build against. srm/interface-contract.md §E.1 only documents reads by service_instance_id or operation_id; nothing keyed by external_ref/caller-facing sessionId. Needs SRM-side input: is there an endpoint (existing or planned) to read a capability_instance by external_ref? If we resolve service_instance_id ourselves instead, does GET /internal/service-instances/{id} actually return result_summary/qos_status, or only service_instance-level fields as documented?
-
event.srm.operation.status semantics for backend-driven drops are undefined. SrmOperationStatusV1.state (§C.1) is accepted | failed_before_start | completed | failed | in_progress — none obviously means "a previously-AVAILABLE session just went UNAVAILABLE." What value/field actually signals this, and does the event reuse the original activate's operation_id?
-
operations.operation_type enum doc is stale. oeg/persistence-model.md line 176 lists deploy, scale, terminate, network_capability — doesn't include network_capability_deactivate, which this branch added to distinguish activate-completions from deactivate-completions in handle_completed.
-
service_specification_id has no catalog backing. Minted fresh (uuid4()) per request with nothing onboarded behind it. srm/interface-contract.md §B.5 marks it "required for catalog/profile validation" — if SRM's real activate handler enforces that, this will reject. Needs confirmation: does SRM validate this today, and if so what's the onboarding path for QoD profiles?